[英]Python - Running Autobahn|Python asyncio websocket server in a separate subprocess or thread
[英]Python asyncio: Running subprocess_exec on a worker thread
因此,我正在使用Python asyncio
模塊(在Linux上)啟動子進程,然后對其進行異步監視。 我的代碼在主線程上運行時工作正常。 但是,當我在輔助線程上運行它時,它將掛起,並且永遠不會調用process_exited
回調。
我懷疑這實際上可能是某種未記錄的缺陷,或者是在工作線程上運行subprocess_exec
問題,可能與實現如何處理后台線程中的信號有關。 但這也可能只是我搞砸了。
一個簡單的,可復制的示例如下:
class MyProtocol(asyncio.SubprocessProtocol):
def __init__(self, done_future):
super().__init__()
self._done_future = done_future
def pipe_data_received(self, fd, data):
print("Received:", len(data))
def process_exited(self):
print("PROCESS EXITED!")
self._done_future.set_result(None)
def run(loop):
done_future = asyncio.Future(loop = loop)
transport = None
try:
transport, protocol = yield from loop.subprocess_exec(
lambda : MyProtocol(done_future),
"ls",
"-lh",
stdin = None
)
yield from done_future
finally:
if transport: transport.close()
return done_future.result()
def run_loop():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop) # bind event loop to current thread
try:
return loop.run_until_complete(run(loop))
finally:
loop.close()
因此,在這里,我設置了一個asyncio
事件循環來執行shell命令ls -lh
,然后為從子流程接收到數據時觸發一個回調,為子流程退出時觸發另一個回調。
如果我只是直接在Python程序的主線程中調用run_loop()
,那么一切都會順利進行。 但是如果我說:
t = threading.Thread(target = run_loop)
t.start()
t.join()
然后發生的事情是成功調用了pipe_data_received()
回調,但是從未調用過process_exited()
,並且程序僅掛起。
在四處asyncio
並查看了asyncio
的實現的asyncio
源代碼unix_events.py
,我發現可能有必要將事件循環手動附加到全局“ child watcher”對象,如下所示:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop) # bind event loop to current thread
asyncio.get_child_watcher().attach_loop(loop)
顯然,兒童觀察者是一個(未記錄的)對象,負責在內部調用waitpid
(或類似的東西)。 但是,當我嘗試這樣做並在后台線程中運行run_event_loop()
時,出現了錯誤:
File "/usr/lib/python3.4/asyncio/unix_events.py", line 77, in add_signal_handler
raise RuntimeError(str(exc))
RuntimeError: set_wakeup_fd only works in main thread
因此,這里看起來該實現實際上進行了檢查,以確保只能在主線程上使用信號處理程序,這使我相信,在當前實現中,實際上在后台線程上使用subprocess_exec
是完全不可能的,而無需更改Python源代碼本身。
我對此是否正確? 可悲的是, asyncio
模塊的文檔非常少,所以我很難對這里的結論充滿信心。 我可能做錯了什么。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.