【发布时间】:2016-11-06 17:02:27
【问题描述】:
我有一个具有以下逻辑的宠物项目:
import asyncio, multiprocessing
async def sub_main():
print('Hello from subprocess')
def sub_loop():
asyncio.get_event_loop().run_until_complete(sub_main())
def start():
multiprocessing.Process(target=sub_loop).start()
start()
如果你运行它,你会看到:
Hello from subprocess
这很好。但我要做的是改为使start()协程:
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.
我试图在没有运气的情况下在子进程端销毁它,但我认为正确的方法是防止它与子进程共享。有可能吗?
更新: 这是完整的失败代码:
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())
【问题讨论】:
-
我没有时间给出完整的答案,但您可能需要考虑一种设计,其中 (a) 您的多处理工作由可以使用例如调用的脚本完成。
subprocess.Popen([sys.executable, "the_script.py"], ...)(b) 这个脚本与它的父级通信,例如。stdout使用设计好的协议(它可能非常简单,例如脚本的单字节控制字符和状态更新)和 (c) 使用 asyncio subprocess API。 -
(我并不是说你应该同时使用
subprocess.Popen和 asyncio 的子进程 API,只是你应该编写你的脚本,以便它可以被控制为任何与语言无关的子进程。) -
@detly 感谢您的建议,但是有很多数据应该由子进程继承。如果有一个简单的解决方案可以避免上述问题,我更喜欢它而不是手动重写所有多处理的东西。
-
这很公平,这不是一件小事。
-
我认为这是可能的,因为我发现了一个似乎有效但仅在 unix 平台上有效的 hack。
sub_loop可以从asyncio.set_event_loop(asyncio.unix_events._UnixSelectorEventLoop())开始,这将为子进程创建一个新循环,而父进程将(希望)被垃圾收集
标签: python unix python-3.5 python-multiprocessing python-asyncio