简体   繁体   English

子进程完成后停止Python脚本

[英]Python script being stopped after a subprocess is completed

When running my script, I am running a set of for loops dynamically. 运行脚本时,我正在动态运行一组for循环。 Basically calling a list of items, checking to see what 'stage' that item needs to be ran in, and then running them all in that order. 基本上是调用项目列表,检查要运行该项目的“阶段”,然后按顺序运行所有项目。 When I am trying to run these loops, it gets through the first object, and then gives a "[1]+ Stopped Script.py" in the terminal. 当我尝试运行这些循环时,它将遍历第一个对象,然后在终端中给出“ [1] + Stopped Script.py”。 I have found ways to start back up my script, but no post about how to avoid this happening entirely. 我已经找到启动脚本的方法,但是没有关于如何完全避免这种情况的文章。

I have tried using Popen , call , check_output , etc. They all get the same result. 我已经尝试使用Popencallcheck_output等,他们都得到了相同的结果。 I am sure it is the other item I am calling that is doing this at the end of it, but I do not think that another program closing out should kill my script, especially not in a subprocess. 我确定这是我正在调用的另一项,但我认为关闭的其他程序不会杀死我的脚本,尤其是在子进程中不会终止。

I have also tried using threading and multiprocessing. 我也尝试过使用线程和多处理。 Both to no avail. 两者均无济于事。

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()

It gets to the DO_THING() and goes through all of that, then when it comes time to call another subprocess it dies out again. 它到达DO_THING()并经历所有这些过程,然后当需要调用另一个子DO_THING()时,它再次消失。 Whether that subprocess lives in DO_THING() or I comment everything out and just get it to hit the output = call("command", shell=True) line again. 不管该子DO_THING()位于DO_THING()还是我注释掉所有内容,然后再次使其击中output = call("command", shell=True)行。 As soon as it goes to use subprocess again it stops. 一旦再次使用子流程,它将停止。

Any suggestions or ways people have found to block whatever is being passed to stop my script? 人们发现有什么建议或方法可以阻止传递给我的脚本停止运行?

(Just as a heads up, I do not have access to the source of the "command" that is causing my script to stop, and the "command" I am using is not important since I can not do anything on that end. I must use this "command" as well.) (仅提防您,我无权访问导致脚本停止的"command"的源,并且我正在使用的"command"并不重要,因为我不能为此做任何事情。我也必须使用此"command" 。)

The message you see indicates that your subprocess is being stopped , not that there is an error. 您看到的消息表明您的子进程正在停止 ,而不是有错误。 This happens for example when typing Ctrl-Z after starting a process in the shell, or equivalently, sending the target process the SIGTSTP signal using the kill command. 例如,在外壳程序中启动进程后键入Ctrl-Z时,或等效地,使用kill命令向目标进程发送SIGTSTP信号时,就会发生这种情况。 Presumably, the command to which you don't have access is receiving this signal. 据推测,您无权访问的command正在接收该信号。 It could even be sending it to itself, although without knowing more about the command it's just speculation as to how or why that's happening. 它甚至可以将其发送给自己,尽管在不了解更多有关命令的情况下,只是猜测如何发生或为什么发生。

You can choose to ignore this signal in Python by using the signal module, specifically the pthread_sigmask() function. 您可以选择使用signal模块(特别是pthread_sigmask()函数pthread_sigmask()在Python中忽略此信号。 One specifies a mask of signals, and what to do about them. 一个指定信号屏蔽,以及如何处理它们。 In this case, you want to ignore the SIGTSTP signal, which an be done with: signal.pthread_sigmask(signal.SIG_BLOCK, (signal.SIGTSTP,)) . 在这种情况下,您要忽略SIGTSTP信号,可通过执行以下操作: signal.pthread_sigmask(signal.SIG_BLOCK, (signal.SIGTSTP,)) (The latter argument is actually a sequence of signals to ignore.) (后一个参数实际上是要忽略的信号序列。)

Running this snippet of code, you should see that you can type Ctrl-Z in the terminal, and the shell should show [1]+ Stopped ... : 运行此代码段,您应该看到可以在终端中键入Ctrl-Z ,并且外壳程序应该显示[1]+ Stopped ...

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

However, using the following code, one will see that the signal is ignored, and the process will continue to "work" (sleep, in this case) regardless of the signal. 但是,使用以下代码,您将看到信号被忽略,并且无论信号如何,该过程将继续“工作”(在这种情况下为睡眠)。 You should just see ^Z at the shell whenever you press Ctrl-Z . 每当您按Ctrl-Z时,您应该只在外壳上看到^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)

To actually use this in your script, ignore the signal before you call the relevant command . 要在脚本中实际使用它,请在调用相关command之前忽略信号。 It is good practice to query a process's signal mask beforehand, and reset it to that value after you're done with command . 优良作法是事先查询进程的信号掩码,并在使用command完成后将其重置为该值。 You should look at the man pages for signal(3) , sigprocmask(2) , and kill(2) for more information about signals and processes. 您应该查看signal(3)sigprocmask(2)kill(2)的手册页,以获取有关信号和进程的更多信息。

Edit for Python <= 2.7 为Python <= 2.7编辑

signal.pthread_sigmask was added in Python 3.3. signal.pthread_sigmask已在Python 3.3中添加。 A solution that should work for earlier versions is to directly ignore the signal, by installing a handler which does just that. 适用于较早版本的解决方案是通过安装处理该信号的处理程序来直接忽略该信号。 For example: 例如:

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)

As with the 3.3 example above, you should just see ^Z if you hit Ctrl-Z , indicating that the signal was ignored. 与上面的3.3示例一样,如果您Ctrl-Z ,您应该只看到^Z Ctrl-Z ,这表明信号被忽略了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM