【问题标题】:Terminating a running script with subprocess使用子进程终止正在运行的脚本
【发布时间】:2020-07-13 19:29:10
【问题描述】:

我正在使用subprocess 执行python 脚本。我可以成功运行脚本。

import subprocess
import time

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

test.py

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

我可以看到消息I am inside test.py 每秒打印一次。但是,当脚本仍在运行时,我无法终止 proc.terminate()

有人可以帮帮我吗?

【问题讨论】:

    标签: python subprocess


    【解决方案1】:

    proc.communicate 等待进程完成,除非您包含超时。您的进程不会退出并且您没有超时,因此communicate 永远不会返回。您可以在通话后使用print 进行验证。相反,添加超时并捕获其异常

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

    【讨论】:

      【解决方案2】:

      首先,不要使用列表来传递subprocess.Popen() 的参数,如果您使用的是shell = True!,请将命令更改为string"python test.py"

      Popen.communicate(input=None, timeout=None)是一个阻塞类方法,它与进程交互,等待进程终止并设置returncode属性。

      由于您的test.py 运行无限while 循环,他将永远不会返回!

      您有 2 个选项可让您生成的进程 proc 超时:

      1. 分配超时关键字参数,例如将过程计时 5 秒,communicate(timeout=5) 方法。如果进程proctimeout 秒后没有终止,则会引发TimeoutExpired exception。捕获此异常并重试通信不会丢失任何输出(在您的情况下,您不需要子输出,但我将在下面的示例中提到这一点)。 注意如果timeout expires,子进程不会被杀死,因此为了正确清理,行为良好的应用程序应该杀死子进程(proc)并完成通信。
      2. 通过使用poll 方法并通过您的调用方法进行计时。

      超时通信

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

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

      【讨论】:

      • 可以使用带有shell=True 的列表...子进程将提供所需的任何转义并将其转换为shell 的字符串。它是一种传递参数的便捷方式,否则如果您只传递一个字符串,您就需要转义。
      • 嗨@tdelaney,在communicate with timeout 为什么我们需要在执行proc.kill() 之后再次通信,请您帮帮我
      猜你喜欢
      • 2013-05-27
      • 1970-01-01
      • 2011-12-10
      • 2021-07-26
      • 2015-10-18
      • 1970-01-01
      • 2010-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多