ホームページ >バックエンド開発 >Python チュートリアル >Python はコマンド ライン ツールを非同期的に呼び出します
自分の Python プログラムでイベント ループに基づく非同期プログラミング手法を採用すると、この手法が優れているからではなく、その手法について考えなければならないため、無意識にその手法に惹かれることになります。プログラムはブロックされています!
たとえば、現在のシナリオでは、MongoDB から未処理のデータをすべて読み取り、画像情報をダウンロードして保存し、データベースの内容を更新します。 Python でよく使われる MongoDB 非同期ドライバーは Motor:
以下のように asyncio と組み合わせて使用します:
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())
このとき、dl_img() での操作がブロックされてしまうと非同期処理の意味がありません。もちろん、非同期ネットワーク リクエスト ライブラリ aiohttp を使用して画像のダウンロードを行うこともできます:
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)
もちろん、システム コマンド ライン ツール (wget など) を直接呼び出して、自分でダウンロードせずにダウンロード タスクを完了することもできます。 。 Python は、サブプロセス標準ライブラリ (古い os.system (cmd) を置き換える) を介してシステム コマンド呼び出しを実装します。 ダウンロード タスクを実行するには、次のものが必要です:
import subprocess as sb sb.run(['wget', img], shell=True)
ただし、この呼び出しメソッドは asyncio イベント ループで直接使用できません。ただし、asyncio は対応するサブプロセス インターフェイスを提供します:
asyncio.create_subprocess_exec(*args, ...) asyncio.create_subprocess_shell(cmd, ...)
どちらのメソッドも asyncio.subprocess.Process インスタンスを返し、そのインターフェイスの設計は完全に subprocess.Popen (上記の subprocess.run() の基礎となる実装) を模倣しています。その使用方法をイベント ループに移植するのは簡単です:
async def dl_img(src): dl = await asyncio.create_subprocess_shell('wget {} -O {}'.format(src, src.split("/")[-1]) await dl.wait()
上記のシナリオでの使用に加えて、コマンド ラインの実行をタスクとしてイベント ループに直接入れることもできます:
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())
概要
Python での非同期プログラミングの意味は、CPU に IO をブロックさせないことです。そのため、これらの操作が非同期タスクにカプセル化されたら、すべてのブロック操作で正しい非同期メソッドを使用することに注意する必要があります。その後のスケジューリングの実行について心配する必要はありません。