Heim > Artikel > Backend-Entwicklung > Was für ein Artefakt! Ein effizientes Python-Crawler-Framework, das einfacher zu verwenden ist als Anfragen!
Kürzlich wurde das Python-Back-End-Projekt des Unternehmens umstrukturiert und die gesamte Back-End-Logik grundsätzlich geändert, um eine „asynchrone“ Coroutine-Implementierung zu verwenden. Als ich den Bildschirm voller Code betrachtete, der mit Async Await (der Implementierung von Coroutinen in Python) dekoriert war, fühlte ich mich plötzlich verwirrt und ratlos.
Obwohl ich schon früher gelernt habe, was eine „Coroutine“ ist, habe ich sie noch nicht eingehend erforscht, also habe ich diese Gelegenheit einfach genutzt, um sie sorgfältig zu lernen. Was ist eine Coroutine?
Einfach ausgedrückt ist Coroutine eine Art Existenz, die auf Threads basiert, aber leichter als Threads ist. Für den Systemkernel haben Coroutinen unsichtbare Eigenschaften, daher wird dieser leichtgewichtige Thread, der von Programmierern verwaltet wird, die ihre eigenen Programme schreiben, oft als „User Space Thread“ bezeichnet. Was sind die Vorteile von Coroutine gegenüber Multithreading?
1. Die Kontrolle über den Thread liegt in den Händen des Betriebssystems, während die Kontrolle über die Coroutine vollständig in den Händen des Benutzers liegt. Daher kann die Verwendung von Coroutinen den Kontextwechsel reduzieren Das Programm läuft und verbessert effektiv die Effizienz des Programms.
2. Beim Erstellen eines Threads beträgt die vom System zugewiesene Standardstapelgröße 1 M, während Coroutinen leichter sind, etwa 1 K, sodass mehr Coroutinen im selben Speicher geöffnet werden können . . 3. Da die Art der Coroutine nicht Multi-Threaded, sondern Single-Threaded ist, ist kein Multithread-Sperrmechanismus erforderlich. Da es nur einen Thread gibt, gibt es keinen Konflikt, der durch das gleichzeitige Schreiben von Variablen verursacht wird. Die Steuerung gemeinsam genutzter Ressourcen in einer Coroutine erfordert keine Sperre, lediglich der Status muss ermittelt werden. Daher ist die Ausführungseffizienz von Coroutinen viel höher als die von Multithreads und vermeidet auch effektiv die Konkurrenz in Multithreads. Anwendbare und nicht anwendbare Szenarien von CoroutinenAnwendbare Szenarien: Coroutinen eignen sich für Szenarien, die blockiert sind und ein hohes Maß an Parallelität erfordern. Nicht anwendbare Szenarien: Coroutinen eignen sich nicht für Szenarien mit einer großen Anzahl von Berechnungen (da das Wesentliche von Coroutinen darin besteht, in einem einzelnen Thread hin und her zu wechseln, sollten Sie dies dennoch tun). Verwenden Sie andere Mittel, um das Problem zu lösen. Erste Erkundung des asynchronen http-Frameworks httpxAn diesem Punkt sollten wir ein allgemeines Verständnis von „Coroutine“ haben, aber wenn die Geschichte an diesen Punkt kommt, glaube ich einigen Freunde sind immer noch voller Zweifel: Wie hilft „Coroutine“ beim Schnittstellentest? Keine Sorge, die Antwort finden Sie unten. Ich glaube, dass Freunde, die Python zum Testen von Schnittstellen verwendet haben, mit der Anforderungsbibliothek vertraut sind. Die in Anfragen implementierte http-Anfrage ist eine synchrone Anfrage, aber tatsächlich ist es aufgrund der E/A-Blockierungseigenschaften von http-Anfragen sehr gut geeignet, Coroutinen zu verwenden, um „asynchrone“ http-Anfragen zu implementieren und die Testeffizienz zu verbessern. Ich glaube, das hat schon vor langer Zeit jemand bemerkt, also habe ich nach einiger Erkundung auf Github erwartungsgemäß endlich eine Open-Source-Bibliothek gefunden, die „asynchrone“ Aufrufe von Coroutinen an http: httpx unterstützt. Was ist httpxhttpx ist eine Open-Source-Bibliothek, die fast alle Anforderungsfunktionen erbt und „asynchrone“ http-Anfragen unterstützt. Einfach ausgedrückt kann httpx als eine erweiterte Version von Anfragen betrachtet werden. Sie können mir folgen, um die Leistungsfähigkeit von httpx zu sehen. InstallationDie httpx-Installation ist sehr einfach und kann in einer Umgebung von Python 3.6 oder höher ausgeführt werden.pip install httpx
import asyncio import httpx import threading import time def sync_main(url, sign): response = httpx.get(url).status_code print(f'sync_main: {threading.current_thread()}: {sign}2 + 1{response}') sync_start = time.time() [sync_main(url='http://www.baidu.com', sign=i) for i in range(200)] sync_end = time.time() print(sync_end - sync_start)
Die Ausgabe nach dem Ausführen ist wie folgt (ein Teil der Schlüsselausgabe wird abgefangen ...):
sync_main: <_MainThread(MainThread, started 4471512512)>: 192: 200 sync_main: <_MainThread(MainThread, started 4471512512)>: 193: 200 sync_main: <_MainThread(MainThread, started 4471512512)>: 194: 200 sync_main: <_MainThread(MainThread, started 4471512512)>: 195: 200 sync_main: <_MainThread(MainThread, started 4471512512)>: 196: 200 sync_main: <_MainThread(MainThread, started 4471512512)>: 197: 200 sync_main: <_MainThread(MainThread, started 4471512512)>: 198: 200 sync_main: <_MainThread(MainThread, started 4471512512)>: 199: 200 16.56578803062439
Die Ausführung des Programms dauerte insgesamt 16,6 Sekunden.
Versuchen wir unten eine „asynchrone“ http-Anfrage:
import asyncio import httpx import threading import time client = httpx.AsyncClient() async def async_main(url, sign): response = await client.get(url) status_code = response.status_code print(f'async_main: {threading.current_thread()}: {sign}:{status_code}') loop = asyncio.get_event_loop() tasks = [async_main(url='http://www.baidu.com', sign=i) for i in range(200)] async_start = time.time() loop.run_until_complete(asyncio.wait(tasks)) async_end = time.time() loop.close() print(async_end - async_start)
Der obige Code verwendet das Schlüsselwort „asyncawait“ in async_main, um „asynchrones“ http über asyncio (asynchrone io-Bibliotheksanforderung) zu implementieren Baidu-Homepage 200 Mal durchsuchen und die benötigte Zeit ausdrucken).
Nachdem Sie den Code ausgeführt haben, können Sie die folgende Ausgabe sehen (einige Schlüsselausgaben wurden abgefangen ...).
async_main: <_MainThread(MainThread, started 4471512512)>: 56: 200 async_main: <_MainThread(MainThread, started 4471512512)>: 99: 200 async_main: <_MainThread(MainThread, started 4471512512)>: 67: 200 async_main: <_MainThread(MainThread, started 4471512512)>: 93: 200 async_main: <_MainThread(MainThread, started 4471512512)>: 125: 200 async_main: <_MainThread(MainThread, started 4471512512)>: 193: 200 async_main: <_MainThread(MainThread, started 4471512512)>: 100: 200 4.518340110778809
Sie können sehen, dass, obwohl die Reihenfolge durcheinander ist (56, 99, 67 ...) (das liegt daran, dass das Programm ständig zwischen Coroutinen wechselt), der Hauptthread nicht wechselt (das Wesentliche). von Coroutinen) Immer noch Single-Threaded).
Der Vorgang dauerte insgesamt 4,5 Sekunden.
Im Vergleich zu den 16,6 Sekunden, die die synchrone Anfrage benötigte, wurde sie um fast 73 % verkürzt!
Wie das Sprichwort sagt: Ein Schritt ist schnell und jeder Schritt ist schnell. In Bezug auf den Zeitverbrauch ist „asynchrones“ httpx tatsächlich viel schneller als synchrones http. Natürlich können „Coroutinen“ nicht nur Schnittstellentests im Hinblick auf die Anforderungseffizienz ermöglichen. Nach der Beherrschung von „Coroutinen“ glaube ich, dass das technische Niveau von Freunden auch auf ein höheres Niveau gebracht werden kann, wodurch ein besseres Test-Framework entworfen werden kann.
Okay, das sind alle heute geteilten Inhalte. Wenn es dir gefällt, gib ihm bitte ein „Gefällt mir“~
Das obige ist der detaillierte Inhalt vonWas für ein Artefakt! Ein effizientes Python-Crawler-Framework, das einfacher zu verwenden ist als Anfragen!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!