python subprocess.call无法正确处理信号

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

这是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的脚本:

import subprocess

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

奇怪的是,使用subproces.Popen()可使此错误消失.

解决方法:

如果python 3.3 subprocess.call实现的等待被中断,则它会通过其Ctrl-C(SIGINT-> KeyboardInterrupt异常)向其子级发送SIGKILL.

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

为了简化起见,从python 3.3来源编辑:

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实现进行对比:

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

真是令人不快的惊喜.当扩展等待和调用接口以容纳超时时,似乎在3.3中引入了此行为.我找不到正确的答案,我有filed a bug.

上一篇:python-process.communicate和getche()失败


下一篇:为什么python子进程输出与shell不同?