将SIGINT信号委托给子进程,然后清理并终止父进程 [英] delegate SIGINT signal to child process and then cleanup and terminate the parent
问题描述
我有一个主要的python(testmain.py)脚本,该脚本使用subprocess.Popen命令执行另一个python脚本(test.py).当我按Ctrl-C时,我希望孩子退出时退出代码为2,然后让父级显示退出代码,然后终止.
I have a main python(testmain.py) script that executes another python script(test.py) using subprocess.Popen command. When I press Ctrl-C , I want the child to exit with exit code 2 and then the parent to display that exit code and then terminate .
我在父脚本和子脚本中都有信号处理程序.
I have signal handlers in both parent and child scripts.
testmain.py
testmain.py
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()
test.py
def signal_handler(signal, frame):
print "exiting: inner function"
exit(2)
signal.signal(signal.SIGINT, signal_handler)
我检查了将信号处理委托给python中的子进程类似于我的问题,但是在那种情况下,父级继续执行它,这是我所不希望的.
I checked Delegate signal handling to a child process in python that is kind of similar to my question but in that case, the parent is continuing it's execution, which I don't want.
我想:1.使用exit(2)退出test.py 2.打印testmain.py中的退出代码3.使用exit(2)退出test.py
I want to: 1.exit test.py with exit(2) 2.print that exit code in testmain.py 3.exit test.py with exit(2)
有人可以提供建议吗? 谢谢.
could someone please provide suggestions to do this? Thanks.
更新:仅在子级(test.py)中处理信号并在父级(testmain.py)中检查返回码即可完成我想要的操作.
UPDATE : Handling the signal only in the child (test.py) and checking the return code in parent(testmain.py) will do what I want .
if rc==2:
print "child was terminated"
exit(2)
但是我想知道是否有一种使用信号处理的干净方法.
but I was wondering if there is a clean way to do this using signal handling.
推荐答案
您的子进程不应该关心父级的操作,即,如果您希望子级以Ctrl + C的特定状态退出,则只需执行以下操作:
Your child process shouldn't care what the parent does i.e., if you want the child to exit with specific status on Ctrl+C then just do that:
import sys
try:
main()
except KeyboardInterrupt: # use default SIGINT handler
sys.exit(2)
或者您可以明确定义信号处理程序:
Or you could define the signal handler explicitly:
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
处理程序和/或多个线程,则行为可能有所不同.
There might be a difference in behavior if there are atexit
handlers and/or multiple threads.
不相关:根据您的main()
函数的功能,在Python中处理信号之前可能会有明显的延迟. Python 2上的某些阻止方法可能会完全忽略信号:使用Python 3或针对特定情况应用自定义变通办法,例如,对某些调用使用timeout参数.
Unrelated: depending on what your main()
function does, there could be a significant delay before a signal is handled in Python. Some blocking methods on Python 2 may ignore the signal completely: use Python 3 or apply a custom workaround for a specific case e.g., using a timeout parameter for some calls.
您可以在父级中以类似方式处理SIGINT
:
You could handle SIGINT
in a similar way in the parent:
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
信号,则您可以使用preexec_fn
参数显式重置必要的处理程序.
Python 2 doesn't restore signals for child processes e.g., if you SIG_IGN
the SIGINT
signal in the parent, you could reset the necessary hanlders explicitly using preexec_fn
parameter.
这篇关于将SIGINT信号委托给子进程,然后清理并终止父进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!