子进程完成后停止Python脚本

时间:2019-02-18 18:37:23

标签: python subprocess

运行脚本时,我正在动态运行一组for循环。基本上是调用项目列表,检查要运行该项目的“阶段”,然后按顺序运行所有项目。当我尝试运行这些循环时,它将遍历第一个对象,然后在终端中给出“ [1] + Stopped Script.py”。我已经找到了备份脚本的方法,但是没有关于如何完全避免这种情况的文章。

我尝试使用Popencallcheck_output等。它们都得到相同的结果。我确定这是我正在调用的另一项,但我认为关闭的另一个程序不会杀死我的脚本,尤其是在子进程中。

我也尝试过使用线程和多处理。两者都无济于事。

def foo(list):
    stages = 0
    for c in things:
        info = load_json_info(c)
        if info["stage"] >= stages:
            stages = info["stage"]
    for p in list:
        use_list(p)
    stages = stages + 1
    for i in range(stages):
        for b in list:
            info = load_json_info(b)
            if info["stage"] == i:
                if info["check"] != "NO":
                    output = call("command", shell=True)
                    if output == 0:
                        DO_THING()
                    else:
                        DONT_DO_THING()
                else:
                    DONT_DO_THING()

它到达DO_THING()并经过所有这些过程,然后当需要调用另一个子流程时,它又消失了。无论该子流程位于DO_THING()中,还是我将所有内容都注释掉,然后再次使其到达output = call("command", shell=True)行。一旦再次使用子流程,它将停止。

人们发现有什么建议或方法可以阻止正在传递的任何内容来阻止我的脚本?

(请注意,我无法访问导致脚本停止的"command"的源,并且我正在使用的"command"并不重要,因为我无法为此要做任何事情。我也必须使用此"command"

1 个答案:

答案 0 :(得分:0)

您看到的消息表明您的子进程正在已停止,而不是出现错误。例如,在外壳程序中启动进程后键入Ctrl-Z时,或等效地,使用SIGTSTP命令向目标进程发送kill信号时,就会发生这种情况。可能是您无权访问的command收到此信号。它甚至可以将其发送给自己,尽管在不了解更多有关命令的情况下,只是猜测这是如何发生或为什么发生的。

您可以选择使用signal模块(特别是pthread_sigmask()函数)在Python中忽略该信号。一个指定信号屏蔽,以及如何处理它们。在这种情况下,您想忽略SIGTSTP信号,可通过执行以下操作:signal.pthread_sigmask(signal.SIG_BLOCK, (signal.SIGTSTP,))。 (后一个参数实际上是要忽略的信号序列。)

运行此代码段,您应该看到可以在终端中键入Ctrl-Z,并且外壳程序应显示[1]+ Stopped ...

import time
duration = 5.0
print('Sleeping for {:0.2f} seconds'.format(duration))
time.sleep(duration)

但是,使用以下代码,将看到信号被忽略,并且无论信号如何,该过程将继续“工作”(在这种情况下为睡眠)。每当您按^Z时,您都应该在外壳上看到Ctrl-Z

import time
import signal
duration = 5.0
print('Sleeping for {:0.2f} seconds, ignoring SIGTSTP'.format(duration))
signal.pthread_sigmask(signal.SIG_BLOCK, (signal.SIGTSTP,))
time.sleep(duration)

要在脚本中实际使用此命令,请在调用相关的command之前忽略该信号。优良作法是事先查询进程的信号掩码,并在完成command后将其重置为该值。您应该查看signal(3)sigprocmask(2)kill(2)的手册页,以获取有关信号和过程的更多信息。

针对Python <= 2.7

编辑

signal.pthread_sigmask是在Python 3.3中添加的。适用于较早版本的解决方案是通过安装处理该信号的处理程序来直接忽略该信号。例如:

import signal
import time

duration = 5.0
signal.signal(signal.SIGTSTP, signal.SIG_IGN)
print 'Sleeping for %f seconds, ignoring SIGTSTP' % duration
time.sleep(duration)

与上述3.3示例一样,如果您击中^Z,则应该只看到Ctrl-Z,表示该信号已被忽略。