我试图为我的python守护进程创建类似超级用户的东西,发现相同的代码在python2中有效,而在python3中不起作用.通常,我来介绍这个最小的示例代码.守护进程#!/usr/bin/env pythonimport signalimport sysimport osde...

我试图为我的python守护进程创建类似超级用户的东西,发现相同的代码在python2中有效,而在python3中不起作用.
通常,我来介绍这个最小的示例代码.
守护进程
#!/usr/bin/env python
import signal
import sys
import os
def stop(*args, **kwargs):
print('daemon exited', os.getpid())
sys.exit(0)
signal.signal(signal.SIGTERM, stop)
print('daemon started', os.getpid())
while True:
pass
主管
import os
import signal
import subprocess
from time import sleep
parent_pid = os.getpid()
commands = [
[
'./daemon.py'
]
]
popen_list = []
for command in commands:
popen = subprocess.Popen(command, preexec_fn=os.setsid)
popen_list.append(popen)
def stop_workers(*args, **kwargs):
for popen in popen_list:
print('send_signal', popen.pid)
popen.send_signal(signal.SIGTERM)
while True:
popen_return_code = popen.poll()
if popen_return_code is not None:
break
sleep(5)
signal.signal(signal.SIGTERM, stop_workers)
for popen in popen_list:
print('wait_main', popen.wait())
如果您运行supervisor.py,然后在其pid上调用kill -15,则它将死于无限循环,因为popen_return_code永远不会不是None.我发现,这基本上是因为添加了threading.Lock用于wait_pid操作(source),但是如何重写代码以使其能够正确处理子退出?
解决方法:
这是一个有趣的案例.
我花了几个小时试图弄清楚为什么会发生这种情况,而我现在想到的唯一一件事就是,在python3和python2.7中已经更改了wait()和poll()的实现.
查看python3 / suprocess.py实现的源代码,我们可以看到调用Popen对象的wait()方法时发生了锁获取,请参见
https://github.com/python/cpython/blob/master/Lib/subprocess.py#L1402.
此锁可防止进一步的poll()调用按预期工作,直到由wait()获得的锁被释放为止,请参见
https://github.com/python/cpython/blob/master/Lib/subprocess.py#L1355
并在那里发表评论
Something else is busy calling waitpid. Don’t allow two
at once. We know nothing yet.
python2.7 / subprocess.py中没有这样的锁,因此这看起来像是它在python2.7中起作用而在python3中不起作用的原因.
但是我没有看到为什么要尝试在信号处理程序中进行poll()的原因,请尝试按以下方式重写您的supervisor.py,这应该在python3和python2.7上都能正常工作
主管
import os
import signal
import subprocess
from time import sleep
parent_pid = os.getpid()
commands = [
[
'./daemon.py'
]
]
popen_list = []
for command in commands:
popen = subprocess.Popen(command, preexec_fn=os.setsid)
popen_list.append(popen)
def stop_workers(*args, **kwargs):
for popen in popen_list:
print('send_signal', popen.pid)
popen.send_signal(signal.SIGTERM)
signal.signal(signal.SIGTERM, stop_workers)
for popen in popen_list:
print('wait_main', popen.wait())
希望这可以帮助
本文标题为:无法在python3中获取子进程返回代码


基础教程推荐
- Python3 三种进程创建方法 2023-09-03
- Pytorch中的Tensorboard与Transforms搭配使用 2023-08-11
- 如何利用Python快速统计文本的行数 2023-08-04
- Python实现发送警告通知到企业微信方法详解 2023-08-11
- python解析.pyd文件的详细代码 2023-08-09
- 云服务器Ubuntu更改默认python版本 2023-09-03
- Python实现K-近邻算法的示例代码 2022-10-20
- python3内存回收__动态类型 / 可变数据类型 / 引用计数 / 引用减少 / 垃圾回收 / 分代回收 / 孤立的引用环 2023-09-04
- API例子:用Python驱动Firefox采集网页数据 | 一起学习Python网络爬虫 2023-09-04
- python开发之virtualenv与virtualenvwrapper(linux下安装与配置) 2023-09-04