简体   繁体   English

使用子进程终止正在运行的脚本

[英]Terminating a running script with subprocess

I am using subprocess to execute a python script.我正在使用subprocess进程执行 python 脚本。 I can successfully run the script.我可以成功运行脚本。

import subprocess
import time

proc = subprocess.Popen(['python', 'test.py', ''], shell=True)
proc.communicate()
time.sleep(10)
proc.terminate()

test.py测试.py

import time
while True:
    print("I am inside test.py")
    time.sleep(1)
    

I can see the message I am inside test.py printed every second.我可以看到I am inside test.py中的消息每秒打印一次。 However, I am not able to terminate the script while it is still running by proc.terminate() .但是,当脚本仍在运行时,我无法终止proc.terminate()

Could someone kindly help me out?有人可以帮我吗?

proc.communicate waits for the process to finish unless you include a timeout. proc.communicate等待进程完成,除非您包含超时。 Your process doesn't exit and you don't have a timeout so communicate never returns.您的进程不会退出并且您没有超时,因此communicate永远不会返回。 You could verify that with a print after the call.您可以在通话后通过print来验证这一点。 Instead, add a timeout and catch its exception相反,添加超时并捕获其异常

import subprocess
import time

proc = subprocess.Popen(['python', 'test.py', ''], shell=True)
try:
    proc.communicate(timeout=10)
except subprocess.TimeoutExpired:
    proc.terminate()

First things first, don't use a list to pass in the arguments for the subprocess.Popen() if you're using the shell = True ,, change the command to string , "python test.py" .首先,如果您使用的是shell = True ,请不要使用列表将 arguments 传递给 subprocess.Popen subprocess.Popen() ,将命令更改为string "python test.py"

Popen.communicate(input=None, timeout=None) is a blocking class method, it shall Interact with process, and Wait for process to terminate and set the returncode attribute. Popen.communicate(input=None, timeout=None)是一个阻塞的 class 方法,它应该与进程交互,并等待进程终止并设置返回码属性。

since your test.py running infinite while loop, he will never return !由于您的test.py运行无限 while 循环,他将永远不会返回!

you have 2 options to timeout the process proc that you have spawned:您有 2 个选项可以使您生成的进程proc超时:

  1. assign the timeout keyword argument in the,eg timing the process for 5 seconds, communicate(timeout=5) method.在例如将进程计时 5 秒、 communicate(timeout=5)方法中分配 timeout 关键字参数。 If the process proc does not terminate after timeout seconds, a TimeoutExpired exception will be raised.如果进程proctimeout秒后没有终止,则会引发TimeoutExpired exception Catching this exception and retrying communication will not lose any output (in your case you dont need the child outputs, but i will mention this in the example below).捕获此异常并重试通信不会丢失任何 output(在您的情况下,您不需要子输出,但我将在下面的示例中提到这一点)。 ATTENTION The child process is not killed if the timeout expires , so in order to cleanup properly a well-behaved application should kill the child process ( proc ) and finish communication.注意如果timeout expires ,子进程不会被杀死,因此为了正确清理,行为良好的应用程序应该杀死子进程( proc )并完成通信。
  2. by using the poll method and do the timing by your calling method.通过使用poll方法并通过调用方法进行计时。

communicate with timeout超时通信

try:
    outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

poll with time.sleep用 time.sleep 轮询

proc = subprocess.Popen('python test.py', shell=True)
t=10
while proc.poll() is None and t >= 0:
    print('Still sleeping')
    time.sleep(1)
    t -= 1
proc.kill()

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

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