Python脚本无法通过Ctrl + C或Ctrl + Break终止

时间:2017-04-12 22:20:22

标签: python asynchronous scripting operating-system signal-handling

我有一个名为myMain.py的简单python脚本,用增量号自动执行另一个python程序,我在CentOS 7上运行它:

#!/usr/bin/python

import os
import sys
import time

def main():
    step_indicator = ""
    arrow = ">"
    step = 2
    try:
        for i in range(0,360, step):
            step_percentage = float(i)/360.0 * 100
            if i % 10 == 0:
                step_indicator += "="
            os.system("python myParsePDB.py -i BP1.pdb -c 1 -s %s" % step)
            print("step_percentage%s%s%.2f" % (step_indicator,arrow,step_percentage)+"%")
    except KeyboardInterrupt:
        print("Stop me!")
        sys.exit(0)


if __name__ == "__main__":
    main()

目前我只知道这个脚本是单线程安全的,但我无法通过Ctrl+C键盘中断来终止它。

我已经阅读了一些相关问题:例如Cannot kill Python script with Ctrl-CStopping python using ctrl+c我意识到Ctrl+Z没有杀死进程,它只是暂停进程并将进程保留在后台。 Ctrl+Break也适用于我的情况,我认为它只会终止我的主线程,但会保留子进程。

我还注意到调用os.system()将从当前正在执行的进程中生成子进程。同时,我还有os个文件I / O函数,os.system("rm -rf legacy/*")将调用myParsePDB.py,这意味着这个myParsePDB.py子进程也会生成子进程。然后,如果我想在Ctrl+C中捕获myMain.py,我应该只守护myMain.py还是应该在它们产生时守护每个进程?

1 个答案:

答案 0 :(得分:0)

这是处理信号处理时可能引发的一般问题。 Python信号也不例外,它是操作系统信号的包装器。因此,python中的信号处理取决于操作系统,硬件和许多条件。但是,如何处理这些问题是类似的。

根据本教程,我引用以下段落:signal – Receive notification of asynchronous system events

  

信号是一种操作系统功能,提供了一种方法   通知您的计划事件,并处理   异步。它们可以由系统本身生成,也可以发送   从一个过程到另一个过程。由于信号中断了常规流量   你的程序,有可能是一些操作(特别是I / O)   如果在中间收到信号,可能会产生错误。

     

信号由整数标识,并在操作中定义   系统C头。 Python公开了适合的信号   平台作为信号模块中的符号。对于下面的例子,我   将使用SIGINT和SIGUSR1。两者通常都是为所有Unix定义的   和类Unix系统一样。

在我的代码中:

for循环中的

os.system("python myParsePDB.py -i BP1.pdb -c 1 -s %s" % step)将执行一段时间,并将花费一些时间在I / O文件上。如果键盘中断传递太快并且在写入文件后没有异步捕获,则信号可能在操作系统中被阻塞,因此我的执行仍然是循环的try子句。 (执行期间检测到的错误称为异常,并非无条件致命:Python Errors and Exceptions)。

因此,使它们异步的最简单方法是等待:

try:
    for i in range(0,360, step):
        os.system("python myParsePDB.py -i BP1.pdb -c 1 -s %s" % step)
        time.sleep(0.2)
except KeyboardInterrupt:
    print("Stop me!")
    sys.exit(0)

它可能会影响性能,但它保证在等待执行os.system()后可以捕获信号。如果需要更好的性能,您可能还想使用其他同步/异步功能来解决问题。

有关更多unix信号参考,请同时查看:Linux Signal Manpage