2014-02-25 19 views
2

我正在创建一个定期调用外部命令的Python程序。外部命令需要几秒钟才能完成。我想通过为SIGINT添加一个信号处理程序来减少外部命令严重终止 的可能性。基本上,我希望SIGINT尝试在终止Python程序之前等待命令 执行。问题在于,外部编程似乎也在 中获取了SIGINT,导致它突然结束。根据http://docs.python.org/2/library/signal.html,我使用外部线程调用该命令,因为 信号的Python文档提到只有主线程接收到信号。 有人可以帮助这一点。 这是我的代码的一个存根。想像一下,外部程序是/ bin中/睡眠:Python:忽略后台进程中的信号

import sys 
import time 
import threading 
import signal 
def sleep(): 
    import subprocess 
    global sleeping 
    cmd = ['/bin/sleep', '10000'] 
    sleeping = True 
    p = subprocess.Popen(cmd) 
    p.wait() 
    sleeping = False 

def sigint_handler(signum, frame): 
    if sleeping: 
    print 'busy, will terminate shortly' 
    while(sleeping): time.sleep(0.5) 
    sys.exit(0) 
    else: 
    print 'clean exit' 
    sys.exit(0) 

sleeping = False 
signal.signal(signal.SIGINT, sigint_handler) 
while(1): 
    t1 = threading.Thread(target=sleep) 
    t1.start() 
    time.sleep(500) 

预期的行为是在程序启动按下Ctrl + C N秒后会导致 它等待(10000 - N)秒,然后退出。发生的事情是程序立即终止。

谢谢!

回答

2

问题是信号处理程序在执行新过程时被修改的方式。从POSIX:

A child created via fork(2) inherits a copy of its parent's signal dis‐ 
positions. During an execve(2), the dispositions of handled signals 
are reset to the default; the dispositions of ignored signals are left 
unchanged. 

所以,你需要做的是:

  1. 忽略SIGINT信号
  2. 启动外部程序
  3. 根据需要

设置SIGINT处理程序这样,外部程序将忽略SIGINT。

当然,当脚本不响应SIGINT时,这会留下(非常)小的时间窗口。但那是你必须忍受的事情。

例如:

sleeping = False 
while(1): 
    t1 = threading.Thread(target=sleep) 
    signal.signal(signal.SIGINT, signal.SIG_IGN) 
    t1.start() 
    signal.signal(signal.SIGINT, sigint_handler) 
    time.sleep(500) 
+0

感谢isedev!对不起,我的延迟响应,其他任务优先。你的解决方案看起来应该可以工作,但由于某种原因,产生的过程仍在接收信号。我更新的主循环与您发布的内容相同。我可以忽略一些特定于Python的复杂性吗? – user3349102