python – 具有超时的异步子进程

我在Python 3中生成具有超时的异步子进程时遇到问题.

我想要实现的目标:我希望异步生成多个进程而不等待结果,但我还要确保每个生成的进程都会在给定的超时内结束.

我在这里发现了类似的问题:Using module ‘subprocess’ with timeoutAsynchronous background processes in Python?但它们并没有解决我的问题.

我的代码看起来像这样.我有Using module ‘subprocess’ with timeout中建议的Command类:

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

  def run(self,timeout):
    def target():
      print('Thread started')
      args = shlex.split(self.cmd)
      self.process = subprocess.Popen(args,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()

然后当我想要产生子进程时:

for system in systems:
  for service in to_spawn_system_info:
    command_str = "cd {0} && python proc_ip.py {1} {2} 0 2>>{3}".format(home_dir,service,system,service_log_dir)
    command = Command(command_str)
    command.run(timeout=60)

当我运行它时,输出似乎等待每个命令生成并结束.我明白了

Thread started
Thread finished
Thread started
Thread finished
Thread started
Thread finished
Thread started
Thread finished

所以我的问题是我做错了什么?现在我开始怀疑是否有可能产生进程并通过超时限制其执行.

为什么我需要这个? spawner脚本将在cron中运行.它将每10分钟执行一次,它必须产生大约20个子进程.我想保证每个子进程都会在脚本再次从cron运行之前结束.

最佳答案
如前所述,对process.communicate()的调用使您的代码等待子进程的完成.但是,如果你只是删除了communication()调用,线程将在产生进程后立即退出,导致你的thread.join()调用过早退出,你将过早地杀掉子进程.要在没有轮询或忙等待的情况下执行您想要的操作,您可以设置一个计时器,如果进程尚未完成,将在超时后终止进程(和运行程序线程):

class Command(object):
  def __init__(self,timeout):
    def target():
      print('Thread started')
      # May want/need to skip the shlex.split() when using shell=True
      # See Popen() constructor docs on 'shell' argument for more detail.
      args = shlex.split(self.cmd)
      self.process = subprocess.Popen(args,shell=True)
      self.timer.start()
      self.process.wait()
      self.timer.cancel()

    def timer_callback():
        print('Terminating process (timed out)')
        self.process.terminate()

    thread = threading.Thread(target=target)
    self.timer = threading.Timer(timeout,timer_callback)
    thread.start()

相关文章

在这篇文章中,我们深入学习了XPath作为一种常见的网络爬虫技巧。XPath是一种用于定位和选择XML文档中特...
祝福大家龙年快乐!愿你们的生活像龙一样充满力量和勇气,愿你们在新的一年里,追逐梦想,勇往直前,不...
今天在爬虫实战中,除了正常爬取网页数据外,我们还添加了一个下载功能,主要任务是爬取小说并将其下载...
完美收官,本文是爬虫实战的最后一章了,所以尽管本文着重呈现爬虫实战,但其中有一大部分内容专注于数...
JSON是一种流行的数据传输格式,Python中有多种处理JSON的方式。官方的json库是最常用的,它提供了简单...
独立样本T检验适用于比较两组独立样本的均值差异,而配对T检验则适用于比较同一组样本在不同条件下的均...