python subprocess.call 不能正确处理信号 [英] python subprocess.call doesn't handle signal correctly

查看:25
本文介绍了python subprocess.call 不能正确处理信号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(我使用的是 Python 3.4.2)我有一个脚本 test.py,它处理 SIGTERM 等.但是,当它被其他脚本调用时,信号处理不正确.

(I'm using Python 3.4.2) I have a script test.py, which handles SIGTERM etc. However, when it's called by some other script, the sig-handling wasn't correct.

这是test.py:

#! /path/to/python3
import time
import signal
import sys

def handleSIG(signal, frame):
    for i in range(10):
        print(i)
    sys.exit()

for sig in [signal.SIGTERM, signal.SIGINT, signal.SIGQUIT, signal.SIGHUP]:
    signal.signal(sig, handleSIG)

time.sleep(30)

如果我只是调用test.py"并执行Ctrl+C",那么它会在控制台上打印 0,1,...,9.但是,如果我使用 subprocess.call 在另一个脚本中调用 test.py,则只会打印 0.例如,这是另一个调用 test.py 的脚本:

If I just call "test.py" and do "Ctrl+C", then it prints 0,1,...,9 to the console. However, if I call test.py in another script using subprocess.call, only 0 will be printed. For example, here's another script that calls test.py:

import subprocess

cmd = '/path/to/test.py'
subprocess.call(cmd)

奇怪的是,使用 subproces.Popen() 可以消除这个错误.

Strangely, using subproces.Popen() makes this error go away.

推荐答案

如果 wait 被中断,python 3.3 subprocess.call 实现会向其子进程发送 SIGKILL,它是由您的 Ctrl-C(SIGINT -> KeyboardInterrupt 异常)决定的.

The python 3.3 subprocess.call implementation sends a SIGKILL to its child if its wait is interrupted, which it is by your Ctrl-C (SIGINT -> KeyboardInterrupt exception).

因此,您会看到处理终端的 SIGINT(发送到整个进程组)的子进程与父进程的 SIGKILL 之间的竞争.

So, you see a race between the child process handling the terminal's SIGINT (sent to the whole process group) and the parent's SIGKILL.

来自 python 3.3 源代码,为简洁起见进行了

From the python 3.3 sources, edited for brevity:

def call(*popenargs, timeout=None, **kwargs):
    with Popen(*popenargs, **kwargs) as p:
        try:
            return p.wait(timeout=timeout)
        except:
            p.kill()
            p.wait()
            raise

将此与 python 2 实现进行对比:

Contrast this with the python 2 implementation:

def call(*popenargs, **kwargs):
    return Popen(*popenargs, **kwargs).wait()

多么令人不快的惊喜.当 waitcall 接口被扩展以适应超时时,这种行为似乎是在 3.3 中引入的.我认为这不正确,我已经提交了一个错误.

What an unpleasant surprise. It appears that this behavior was introduced in 3.3 when the wait and call interfaces were extended to accommodate a timeout. I don't find this correct, and I've filed a bug.

这篇关于python subprocess.call 不能正确处理信号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆