每当子类化mulitprocessing.Process
类并将SIGCHLD
信号绑定到其中时,python解释器会引发以下错误:
Exception AttributeError: "'MyClass' object has no attribute '_popen'" in <Finalize object, dead> ignored
但我的班级却有预期的行为。
以下是信号处理的样子:
import os
import signal
import multiprocessing
class Actor(multiprocessing.Process):
def __init__(self, *args, **kwargs):
self.bind_signals_handlers()
...
super(Actor, self).__init__(*args, **kwargs)
def on_children_exit(self):
"""Signal handler to be called on SIGCHLD.
This handler will be called on every SIGCHLD signal received
by the actor. SIGCHLD is raised on process interuptions and on
process death, so you can override this handler to set up
the behavior you'd like.
As a default this handler will check if a child process
as exited, and that's it.
"""
# Make sure we do the waitpid over the parent process
# and not from any children.
# see http://stackoverflow.com/questions/5783183/python-multiprocessing-issue-misunderstanding
# see http://bugs.python.org/issue9535
if os.getpid() == self.pid:
pid, status = os.waitpid(-1, os.WNOHANG)
if pid:
print "Actor's child with pid {} exited".format(pid)
def bind_signals_handlers(self):
def sig_child_handler(signum, frame):
self.on_children_exit()
def sig_shutdown_handler(signum, frame):
self.stop()
signal.signal(signal.SIGTERM, sig_shutdown_handler)
signal.signal(signal.SIGINT, sig_shutdown_handler)
signal.signal(signal.SIGCHLD, sig_child_handler)
知道是什么导致了警告,以及如何解决它?
非常感谢!
答案 0 :(得分:3)
我终于通过捕获AttributeError
并检查回溯来找到解决方案。碰巧在pid
实例启动之前访问multiprocessing.Process
属性会引发AttributeError
。
我没有找到任何关于它的文档。
答案 1 :(得分:1)
我在研究类似异常时遇到了这个问题:
File "/usr/local/Cellar/python/3.6.5_1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/multiprocessing/process.py", line 99, in start
assert self._popen is None, 'cannot start a process twice'
AttributeError: 'MyProcess' object has no attribute '_popen'
在我的情况下,问题的根源是我忘记在适当的地方调用Process
的构造函数:
class MyProcess(multiprocessing.Process):
def __init__(self, settings):
super(MyProcess, self).__init__() # Don't forget this!
...
很明显,该调用存在于原始问题中,但是由于它是在子类构造函数的末尾调用的,因此如果这是原因,我将不会感到惊讶(尽管我不确定是否移动调用是在这种情况下的适当补救措施。