我使用Python 3.5和multiprocessing
模块处理套接字并遇到意外行为。我的程序本质上是一些运行的线程,直到客户端收到某条消息告诉它停止。
如果我像这样执行它,我会得到一个BrokenPipeError
来破坏程序,尽管while True
循环和except
阻止。
#!/usr/bin/env python3
import signal
import traceback
from multiprocessing.dummy import Pool
from process import Process
def main():
while True:
try:
# a Process has a couple threads
process = Process()
listener_pool = Pool(processes=1)
sender_pool = Pool(processes=1)
# blocking socket client that runs forever
listener_pool.apply_async(process.listener_thread.run, ())
# blocking socket server that runs forever
sender_pool.apply_async(process.sender_thread.run, ())
return 0
except BrokenPipeError:
traceback.print_exc()
# closing connections
process.emitter_thread.socket.close()
process.listener_thread.socket.close()
if __name__ == '__main__':
main()
但是,当我在返回之前添加signal.pause()
权限时,不仅代码按预期运行,而且任何时候都不会引发BrokenPipeError
。
#!/usr/bin/env python3
import signal
import traceback
from multiprocessing.dummy import Pool
from process import Process
def main():
while True:
try:
# a Process has a couple threads
process = Process()
listener_pool = Pool(processes=1)
sender_pool = Pool(processes=1)
# blocking socket client that runs forever
listener_pool.apply_async(process.listener_thread.run, ())
# blocking socket server that runs forever
sender_pool.apply_async(process.sender_thread.run, ())
signal.pause()
return 0
except BrokenPipeError:
traceback.print_exc()
# closing connections
process.emitter_thread.socket.close()
process.listener_thread.socket.close()
if __name__ == '__main__':
main()
根据docs,信号只能由主线程处理,但两个套接字都由辅助线程处理。 signal.pause()
做什么来防止套接字在同一个上下文中被调用时被破坏?
答案 0 :(得分:1)
apply_async
,正如其名称所暗示的那样立即返回。因此,在程序的第一个版本中,主线程在启动子线程时退出(虚拟进程只是threads using the multiprocessing api)。
因此主线程在异常发生之前很久就退出try
块。
在第二种情况下,signal.pause()
强制主线程在try
块中等待,它将捕获异常。
请注意,这是一个脆弱的解决方案,因为接收任何信号将使signal.pause()
恢复并且主线程退出。