python - 将 SIGINT 信号委托(delegate)给子进程,然后清理并终止父进程

标签 python linux subprocess signals sigint

我有一个主 python(testmain.py) 脚本,它使用 subprocess.Popen 命令执行另一个 python 脚本(test.py)。当我按 Ctrl-C 时,我希望 child 以退出代码 2 退出,然后 parent 显示该退出代码然后终止。

我在父脚本和子脚本中都有信号处理程序。

测试主程序

def signal_handler(signal, frame):
    print "outer signal handler"
    exit(2)
signal.signal(signal.SIGINT, signal_handler) 

def execute()
proc=subprocess.Popen("python test.py",shell=True)
    streamdata=proc.communicate()[0]
    rc=proc.returncode
    print "return code:",rc

execute()

测试.py

def signal_handler(signal, frame):
    print "exiting: inner function"
    exit(2)
signal.signal(signal.SIGINT, signal_handler)

我检查了Delegate signal handling to a child process in python这有点类似于我的问题,但在那种情况下, parent 继续执行它,这是我不想要的。

我想: 1.exit test.py with exit(2) 2.print testmain.py 中的退出代码 3.exit test.py with exit(2)

有人可以提供建议吗? 谢谢。

更新:仅在子级 (test.py) 中处理信号并检查父级 (testmain.py) 中的返回码将执行我想要的操作。

if rc==2:
   print "child was terminated"
   exit(2)

但我想知道是否有一种干净的方法可以使用信号处理来做到这一点。

最佳答案

您的子进程不应该关心父进程做什么,即,如果您希望子进程以 Ctrl+C 的特定状态退出,那么只需这样做:

import sys

try:
    main()
except KeyboardInterrupt: # use default SIGINT handler
    sys.exit(2)

或者您可以显式定义信号处理程序:

import os
import signal

def signal_handler(signal, frame):
    os.write(1, b"outer signal handler\n")
    os._exit(2)
signal.signal(signal.SIGINT, signal_handler)
main()

如果有 atexit 处理程序和/或多个线程,行为可能会有所不同。

无关:根据您的 main() 函数的作用,在 Python 中处理信号之前可能会有明显的延迟。 Python 2 上的一些阻塞方法可能会完全忽略该信号:使用 Python 3 或针对特定情况应用自定义解决方法,例如,对某些调用使用超时参数。


您可以在父级中以类似的方式处理 SIGINT:

for cmd in commands:
    process = Popen(cmd)
    try:
        process.wait()
    except KeyboardInterrupt:
        # child process may still be alive here
        for _ in range(5): # wait a while
           if process.poll() is not None:
               break # the process is dead
           time.sleep(.1)
        else: # no break, kill the process explicitly
           try:
               process.kill()    
           except OSError:
               pass
        sys.exit("Child exited with %d" % process.wait())

Python 2 不会为子进程恢复信号,例如,如果您SIG_IGN 父进程中的SIGINT 信号,you could reset the necessary hanlders explicitly using preexec_fn parameter .

关于python - 将 SIGINT 信号委托(delegate)给子进程,然后清理并终止父进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32487700/

相关文章:

python - 使用 python 子进程和 ssh 读取远程文件?

python - Python 2.6.1 中的 urllib2 是否支持通过 https 进行代理

python - 使用正确的返回值修补相同的对象

linux - Bash `wait` 命令,等待超过 1 个 PID 完成执行

linux - Haskell:quoteFile 在 unicode 字符上带有 "invalid byte sequence"的文本文件上失败

python - 终止后从 tcpdump 子进程获取 stdout

python - 如果 python 是用 C 编写的,为什么 python 语言中的所有内容都是对象?

python - 用货币标记列值,字符串单元格除外

linux - 将行作为参数传递给脚本

python - 使用 sudo 在 python 中运行 Linux 子进程