4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

python並列/非同期実行備忘録

Posted at

切掛

Pythonの非同期実行のネタは似たようなもの(公式の翻訳/再編集?)が多かった。
頭が固くなったオジサンには厳しいので、実例を探して複数言語のサイト見て、試行錯誤してやっと動いたので、肝だけを纏めてみた。

概要

例は全部Windowsで外部コマンド実行のパターン
解説はほぼなし。

PIDでチェック

簡単でいいね。オジサンがパッと思いついて作ったのがこれ。

pid.py
import subprocess
from time import sleep
procs = {}
for h in servers:
    p = subprocess.Popen(["some", "command"], ...)
    # subprocess.runでstdout=PIPEでも動きそうだが未調査
    procs[p.pid] = p

while procs:
    for pid in list(procs):
        if procs[pid].poll in not None:
            del procs[pid]
    sleep(x)

procsは端からpのlistにしておいてもいいけど、
このやり方だと最後に空になるのがお気に入り。

並列1(STDOUT不要)

実行する対象が何かを生成してくれる場合はこれでOK。
run関数が非同期実行対象。
最初に作ったときはrun_until_completeで呼び出すからcreate_subprocess_shellだけで待ってくれるのかと思っていた。

async1.py
import asyncio
from asyncoio.subprocess import DEVNULL

async def run(param):
    # 以下2つどっちでも動く
    p = await asyncio.create_subprocess_exec(*["some", "command", param],
           stdout=DEVNULL, ...)
    p = await asyncio.create_subprocess_shell("some command %s" % param,
           stdout=DEVNULL, ...)

    await p.wait()

if sys.platform.startswith('win'):
    loop = asyncio.ProactorEventLoop()
    asyncio.set_event_loop(loop)
else:
    loop = asyncio.get_event_loop()

funcs = asyncio.gather(*[run(p) for p in parameters])
loop.run_until_complete(funcs)

並列2(STDOUT必要)

実行対象の標準出力を利用して何かをする場合はこっち。
ただし結果はmainのretに終了順に返ってくるので、それに耐えられないと駄目。

async_stdout.py
import asyncio
from asyncoio.subprocess import PIPE
import sys

async def run(param):
    p = await asyncio.create_subprocess_shell("some command %s"  param,
            stdout=PIPE, ...)
    return await (p.communicate())[0].decode('code').splitlines()

async def main():
    funcs = asyncio.gather(*[run(p) for p in parameters]*)
    for f in asyncio.as_completed(funcs):
        ret = await f

if sys.platform.startswith('win'):
    loop = asyncio.ProactorEventLoop()
    asyncio.set_event_loop(loop)
else:
    loop = asyncio.get_event_loop()

loop.run_until_complete(main())

備考

なんか似たようなことばかり書いている気がする。
次はopenpyxlのことでも書くか。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?