【问题标题】:How to call a system command with specified time limit in Python? [duplicate]如何在 Python 中调用具有指定时间限制的系统命令? [复制]
【发布时间】:2015-02-19 17:44:55
【问题描述】:

我正在创建一个调用一些系统命令的 Python 应用程序。但是,如果它们花费太多时间(例如 10 秒),我希望它终止这些命令。我尝试自己做这件事,使用一些子流程——但没有多大成功。在stackoverflow上搜索后,我发现了以下问题: Using module 'subprocess' with timeout

它有一个答案,几乎对我有用 - 问题是,当进程“终止”时,它实际上 不是 - 事实上,即使我的脚本完成后,该过程仍然在后台运行。当然这不是一个理想的效果,但我找不到解决方法。这个问题有首选的解决方案吗?

来自提到的答案(坏的)的代码供参考:

import subprocess, threading

class Command(object):
    def __init__(self, cmd):
        self.cmd = cmd
        self.process = None

    def run(self, timeout):
        def target():
            print 'Thread started'
            self.process = subprocess.Popen(self.cmd, shell=True)
            self.process.communicate()
            print 'Thread finished'

        thread = threading.Thread(target=target)
        thread.start()

        thread.join(timeout)
        if thread.is_alive():
            print 'Terminating process'
            self.process.terminate()
            thread.join()
        print self.process.returncode

command = Command("echo 'Process started'; sleep 2; echo 'Process finished'")
command.run(timeout=3)
command.run(timeout=1)

【问题讨论】:

  • 如果您可以使用 Python ≥3.3,则 Popen.wait() 有一个 timeout 参数。如果孩子没有在超时期限内完成,这将引发 TimeoutExpired 异常。然后可以调用Popen.kill()强制终止子进程。
  • 谢谢,但我用的是 2.7.6

标签: python multithreading


【解决方案1】:

您可以在这里找到答案:

How to terminate a python subprocess launched with shell=True

只需将preexec_fn=os.setsid 添加到Popen 命令

终止使用:

os.killpg(self.process.pid, signal.SIGTERM)

代替:

self.process.terminate()

别忘了import os,signal

所以你会得到:

import subprocess, threading
import os,signal
class Command(object):
    def __init__(self, cmd):
        self.cmd = cmd
        self.process = None

    def run(self, timeout):
        def target():
            print 'Thread started'
            self.process = subprocess.Popen(self.cmd, shell=True, preexec_fn=os.setsid)
            self.process.communicate()
            print 'Thread finished'

        thread = threading.Thread(target=target)
        thread.start()

        thread.join(timeout)
        if thread.is_alive():
            print 'Terminating process'
            os.killpg(self.process.pid, signal.SIGTERM)
            thread.join()
        print self.process.returncode

command = Command("echo 'Process started'; sleep 2; echo 'Process finished'")
command.run(timeout=3)
command.run(timeout=1)

【讨论】:

  • 谢谢,完成了这项工作。你能解释一下为什么以前的版本(带有终止())不起作用吗?
  • 如果是 dup,将其标记为 dup。
猜你喜欢
  • 2011-04-27
  • 2013-06-19
  • 1970-01-01
  • 2018-10-06
  • 1970-01-01
  • 2014-07-18
  • 1970-01-01
  • 2021-01-16
  • 1970-01-01
相关资源
最近更新 更多