3

나는 다음과 같은 논리를 갖는 애완 동물 프로젝트가 있습니다. 하지만 제가이해야 할 것은 대신 start() 코 루틴하게하는 것입니다 : 여기 asyncio + 멀티 + 유닉스

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

문제입니다 :

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

그것을 실행하기를, 내가 그런 일을해야 할 하위 프로세스가 생성 될 때, 이 복제 된 전체 파이썬 환경을 얻는다, 그래서 이벤트 루프가 이미 실행 중입니다

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. 

내가 행운과 서브 프로세스 측면에서 그것을 파괴하려고하지만 올바른 방법으로 홍보라고 생각합니다 이벤트가 서브 프로세스와 공유된다. 어떻게 든 가능할까요?

UPDATE : 여기 전체 실패 코드입니다. 당신은 항상 당신이 코드를합니다 (if __name__ == '__main__': 부분을 실행하는 방법을 확인하기 위해 검사를 추가해야

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

I 전체 응답 시간이 없어,하지만 (a)받은 멀티 물건이 어디 당신이 디자인을 고려할 수 있습니다 eg를 사용하여 호출 할 수있는 스크립트로 수행됩니다. '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

첫째, 당신은을 사용하는 것이 좋습니다 루프 내에서 파이썬 하위 프로세스를 실행하려는 경우 ProcessPoolExecutor으로을 입력하십시오. 문제에 관해서는, 당신은 새로운 루프를 설정 event loop policy 기능을 사용할 수 있습니다

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'는 코 루틴 (coroutine)이므로, 예를 들어'await' 또는'asyncio.wait_for'를 사용하여 서브 프로세스에 쉽게 참여할 수 있습니다. 'ProcessPoolExecutor'는 또한 많은 작업자를 지정할 수있게 해줍니다. – Vincent

+1

생성 된 하위 프로세스에서 새 이벤트 루프를 만들 필요성을 지적 해 주셔서 감사합니다. 이것은 제가 누락 된 중요한 부분이었습니다 - 그렇지 않으면 매우 잘못된 '잘못된 파일 설명자'오류가 발생했습니다. –

1

귀하의 하위 프로세스는 모든 것을 실행 당신에게 슬픔 (저항 할 수 없었다)을주는 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

이것은 유닉스와 관련이있는 것으로 추측됩니다. 왜냐하면이 결과는 같은 결과로 끝납니다. 정확히 같은 예외를 의미합니다. – Grief

+0

@Grief : Linux 환경에서 문제를 재현 할 수 있는지 확인해 보겠습니다. – Gerrat

+0

그건 그렇고, 그들은 그 부분을 python3 문서에서 변경했습니다. '(Windows에서) if __name__ == '__main__'부분이 필요한 이유에 대한 설명은 프로그래밍 지침을 참조하십시오. https://docs.python.org/2/library/multiprocessing.html#multiprocessing- 프로그래밍 및 지금은 단지'왜 __name__ == '__main__'부분이 필요한지에 대한 설명은 프로그래밍 지침을 참조하십시오. 나는 여기에서 바뀌지 않았으며 Windows 언급의 제거는 단순한 크로스 플랫폼 코딩. – Grief