Wenn Sie in Ihrem Python-Programm eine asynchrone Programmiermethode verwenden, die auf Ereignisschleifen basiert, werden Sie sich unbewusst davon angezogen fühlen, nicht weil diese Methode großartig ist, sondern weil Sie einen Weg finden müssen, um sicherzustellen, dass kein Link vorhanden ist Das Programm ist blockiert!
Das aktuelle Szenario besteht beispielsweise darin, alle unverarbeiteten Daten aus MongoDB zu lesen, die Bildinformationen herunterzuladen und dann zu aktualisieren. Der in Python häufig verwendete asynchrone MongoDB-Treiber ist Motor:
Die Methode zur Verwendung in Kombination mit Asyncio ist wie folgt: Der Vorgang blockiert, sodass die asynchrone Verarbeitung bedeutungslos ist. Natürlich können Sie weiterhin die asynchrone Netzwerkanforderungsbibliothek aiohttp verwenden, um das Herunterladen von Bildern zu erreichen:
import motor.motor_asyncio import asyncio client = motor.motor_asyncio.AsyncIOMotorClient() db = client.test_database async def run(): async for mm in db.test_database.find({"status": 0}): print(mm['img_src']) # Download Image Here # dl_img(mm['img_src']) await db.test_database.update({"_id": mm['_id']}, {"$set": {"status":1}}) loop = asyncio.get_event_loop() loop.run_until_complete(run())
Natürlich können Sie das Systembefehlszeilentool (z. B. wget) auch direkt aufrufen ), ohne es selbst herunterzuladen. Python implementiert Systembefehlsaufrufe über die Unterprozess-Standardbibliothek (anstelle der alten os.system(cmd)) Zum Ausführen der Download-Aufgabe benötigen Sie jedoch nur Folgendes:
async with session.get(img) as resp: with open(img.split("/")[-1], 'wb') as fd: while True: chunk = await resp.content.read(1024) if not chunk: break fd.write(chunk)
Dies ist jedoch der Fall Die Aufrufmethode kann nicht direkt in der Ereignisschleife von Asyncio verwendet werden, aber Asyncio stellt die entsprechende Unterprozessschnittstelle bereit:
import subprocess as sb sb.run(['wget', img], shell=True)
Beide Methoden geben eine asyncio.subprocess.Process-Instanz und ihre Schnittstelle zurück Das Design imitiert vollständig subprocess.Popen (die oben erwähnte zugrunde liegende Implementierung von subprocess.run()), sodass seine Verwendung leicht in die Ereignisschleife übertragen werden kann:
asyncio.create_subprocess_exec(*args, ...) asyncio.create_subprocess_shell(cmd, ...)
Zusätzlich zur Verwendung im obigen Szenario können Sie die Ausführung der Befehlszeile auch direkt als Aufgabe in die Ereignisschleife einfügen:
async def dl_img(src): dl = await asyncio.create_subprocess_shell('wget {} -O {}'.format(src, src.split("/")[-1]) await dl.wait()
Zusammenfassung
Die Bedeutung der asynchronen Programmierung in Python besteht darin, die CPU nicht IO blockieren zu lassen. Daher müssen Sie darauf achten, bei jedem Blockierungsvorgang die richtige asynchrone Methode zu verwenden. Sobald diese Vorgänge in asynchrone Aufgaben gekapselt sind, gibt es Sie müssen sich keine Gedanken über die spätere Ausführung der Planung machen.loop = asyncio.get_event_loop() sb = asyncio.create_subprocess_shell('exit 7', loop=loop) proc = loop.run_until_complete(sb) exitcode = loop.run_until_complete(proc.wait())