Python多处理,重启时终止进程和防止僵尸的问题
解决方案: 多亏了Rick Sanders,在终止进程后添加此函数可以解决此问题: 僵尸进程是在进程终止时创建的,除非它们被收获(通过请求退出代码)。它们保留的目的是让父级可以请求其退出代码,并且由于我的脚本没有真正退出,它的进程被Python多处理,重启时终止进程和防止僵尸的问题,python,python-multiprocessing,python-3.5,Python,Python Multiprocessing,Python 3.5,解决方案: 多亏了Rick Sanders,在终止进程后添加此函数可以解决此问题: 僵尸进程是在进程终止时创建的,除非它们被收获(通过请求退出代码)。它们保留的目的是让父级可以请求其退出代码,并且由于我的脚本没有真正退出,它的进程被execv(file,args)替换,父级从不请求退出代码,僵尸进程将保留。这适用于我的OSX和Debian系统 我正在编写一个非常大的脚本,最近实现了多处理和IMAP来监听电子邮件。在实现此功能之前,我已经实现了一个restart命令,我可以在命令行中输入该命令,
execv(file,args)
替换,父级从不请求退出代码,僵尸进程将保留。这适用于我的OSX和Debian系统
我正在编写一个非常大的脚本,最近实现了多处理和IMAP来监听电子邮件。在实现此功能之前,我已经实现了一个restart命令,我可以在命令行中输入该命令,以在编辑后刷新脚本,简而言之,它执行以下操作:
if ipt = ':rs':
execv(__file__)
不过,在这期间,它会打印出一堆废话
我还有一个进程运行在另一个对象中,它在While循环中侦听Google的IMAP服务器,如下所示:
While True:
mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login('myemail@gmail', 'mypassword')
mail.list()
mail.select("inbox")
result, data = mail.uid('search', None, 'All')
latest_email_uid = data[0].split()[-1] #grabs the most recent email by
#unique id number
if int(latest_email_uid) != int(last_email_uid): # set earlier from sql
# database
# do stuff with the mail
else:
continue
通过观看top,我注意到我重新启动时正在创建僵尸,所以我创建了一个终止函数:
def process_terminator(self):
self.imap_listener.terminate()
我在重新启动时称之为:
if ipt == ':rs':
self.process_object.terminate()
execv(__file__)
然而,僵尸进程仍然存在。因此,经过几个小时的工作后,我意识到在调用函数后添加time.sleep period并将局部变量设置到进程“exitcode”或打印进程“exitcode”将允许进程终止,即使只需0.1秒:
if ipt == ':rs':
self.process_object.terminate()
time.sleep(.1)
print(self.process_object.imap_listener.exitcode)
execv(__file__)
不过,OSX中的情况并非如此,只需执行一个进程“.terminate()函数即可结束该进程,但是在我的debian机器上,我必须有一个睡眠(n)周期,并且必须以某种形式或方式引用进程“exitcode”,以防它死机
我也尝试过使用.join,不过这会挂断我的整个脚本。我曾尝试创建变量,使流程在(例如)self.terminated=1时中断其while循环,然后加入,但这也不起作用
我在运行exec('quit')时没有这个问题,只要我终止进程,.join()就不起作用
有人能指出我的误解吗?我尝试过自己做研究,但没有找到足够的解决方案,我知道流程不应该被明确终止,因为它们不会很好地退出,但在工作数小时后,我没有找到其他方法
很抱歉,我没有更多的代码要提供,如果需要,我会尽力提供更多,这些只是我脚本中的相关代码片段(1000多行)。您可以从这里开始:。父进程必须在其子进程退出时获取它们,例如使用waitpid():
等待特定子进程终止并返回已死亡进程的pid,如果没有此类子进程,则返回-1。在某些系统上,值为0表示仍有进程在运行 啊,这就解释了为什么我必须先读取退出代码,然后才能将其从进程表中删除。我会调整我的代码,看看这是否能解决它。非常感谢。令人惊叹的!这起作用了:
def process_terminator(self):self.imap_listener.terminate()waitpid(self.imap_listener.pid,0)
至少在OSX上,现在将在我的debian系统上试用它。。。