3

は、私は次のロジックを持つペットのプロジェクトを持っています。しかし、私がしなければならない代わりにstart()コルーチンようにすることです。それを実行するにはasyncio +マルチプロセッシング+ UNIX

async def start(): 
    multiprocessing.Process(target=sub_loop).start() 

を、私はそのような何かしなければならない。ここで

asyncio.get_event_loop().run_until_complete(start()) 

することは問題である:サブプロセスが作成されたとき、それはクローン化された全体のPython環境を取得しますので、イベントループは、すでにそこに実行されています

Process Process-1: 
Traceback (most recent call last): 
    File "/usr/lib/python3.5/multiprocessing/process.py", line 249, in _bootstrap 
    self.run() 
    File "/usr/lib/python3.5/multiprocessing/process.py", line 93, in run 
    self._target(*self._args, **self._kwargs) 
    File "test.py", line 7, in sub_loop 
    asyncio.get_event_loop().run_until_complete(sub_main()) 
    File "/usr/lib/python3.5/asyncio/base_events.py", line 361, in run_until_complete 
    self.run_forever() 
    File "/usr/lib/python3.5/asyncio/base_events.py", line 326, in run_forever 
    raise RuntimeError('Event loop is running.') 
RuntimeError: Event loop is running. 

私は運とサブプロセス側でそれを破壊しようとしたが、私は正しい方法でのPRであることを考えますイベントをサブプロセスと共有します。どういうわけか可能ですか?

UPDATE:ここ 完全な失敗コードです:

import asyncio, multiprocessing 

import asyncio.unix_events 

async def sub_main(): 
    print('Hello from subprocess') 

def sub_loop(): 
    asyncio.get_event_loop().run_until_complete(sub_main()) 


async def start(): 
    multiprocessing.Process(target=sub_loop).start() 

asyncio.get_event_loop().run_until_complete(start()) 
+0

:あなたの問題については、新しいループを設定するevent loop policy機能を使用することができます例えば、スクリプトを使用して呼び出すことができます。 'subprocess.Popen([sys.executable、the_script.py"]、...) '(b)このスクリプトは、例えばその親と通信します。 (例えば、スクリプトやステータスの更新には完全に単純な制御文字を使用することができます)、(c)[asyncio subprocess API](https://docs.python.org/)を使用して、 'stdout' 3/library/asyncio-subprocess.html)。 – detly

+0

( 'subprocess.Popen'とasyncioのサブプロセスAPIを同時に使うべきではありません。あなたがスクリプトを記述して言語に依存しないサブプロセスとして制御できるようにするだけです) – detly

+0

@detly提案していただきありがとうございますが、サブプロセスによって継承されるべきデータがたくさんあります。上記の問題を回避する簡単な解決策がある場合は、すべてのマルチプロセッシングを手作業で書き直すのではなく、それを好むでしょう。 – Grief

答えて

4

まず、あなたはを使用することを検討すべきですループ内からPythonのサブプロセスを実行する予定の場合はProcessPoolExecutorのを使用してください。私は完全な答えのための時間を持っていませんが、(a)は、あなたのマルチプロセッシングのものがあるデザインを検討する必要があります

import asyncio 
from concurrent.futures import ProcessPoolExecutor 

async def sub_main(): 
    print('Hello from subprocess') 

def sub_loop(): 
    loop = asyncio.new_event_loop() 
    asyncio.set_event_loop(loop) 
    loop.run_until_complete(sub_main()) 

async def start(executor): 
    await asyncio.get_event_loop().run_in_executor(executor, sub_loop) 

if __name__ == '__main__': 
    executor = ProcessPoolExecutor() 
    asyncio.get_event_loop().run_until_complete(start(executor)) 
+0

右...私はこの明白な関数 'asyncio.new_event_loop()'を見逃しているので、私は目が見えないようです。ありがとう!その場合、 'ProcessPoolExecutor'の利益は何か私に説明してください。 – Grief

+1

@Grief 'run_in_executor'はコルーチンです。たとえば、' await'や 'asyncio.wait_for'を使って簡単にサブプロセスに参加することができます。 'ProcessPoolExecutor'では、いくつかのワーカーを指定することもできます。 – Vincent

+1

作成したサブプロセスに新しいイベントループを作成する必要があることを指摘してくれてありがとう。これは私が見逃していた重要なビットでした - そうでなければ、非常にあいまいな 'Bad file descriptor'エラーが発生していました。 –

1

あなたはいつもあなたがコード(if __name__ == '__main__':一部を実行しているかを確認するためのチェックを追加する必要がありますにあなたのサブプロセスがすべてを実行しています。あなた悲しみ(抵抗できなかった)を与えて、2回目のモジュール。

import asyncio, multiprocessing 

async def sub_main(): 
    print('Hello from subprocess') 

def sub_loop(): 
    asyncio.get_event_loop().run_until_complete(sub_main()) 


async def start(): 
    multiprocessing.Process(target=sub_loop).start() 

if __name__ == '__main__': 
    asyncio.get_event_loop().run_until_complete(start()) 
+0

これは同じ結果で終わるので、これはUNIX関連であると思います。私はまったく同じ例外を意味します。 – Grief

+0

@Grief:Linux環境で問題を再現できるかどうかを確認します。 – Gerrat

+0

ところで、彼らはpython3のドキュメントでその部分を変更しました。 '(Windows上で)if __name__ == '__main__'部分が必要な理由については、プログラミングガイドラインを参照してください。https://docs.python.org/2/library/multiprocessing.html#multiprocessing-プログラミングに関するガイドラインを参照してください。ここでは何も変更されていないと考えられています.Windowsの言及の削除は、十字架へのプッシュだけですプラットフォームコーディング。 – Grief

関連する問題