• <bdo id='PiSjD'></bdo><ul id='PiSjD'></ul>

      <tfoot id='PiSjD'></tfoot>

      <small id='PiSjD'></small><noframes id='PiSjD'>

      1. <legend id='PiSjD'><style id='PiSjD'><dir id='PiSjD'><q id='PiSjD'></q></dir></style></legend>
      2. <i id='PiSjD'><tr id='PiSjD'><dt id='PiSjD'><q id='PiSjD'><span id='PiSjD'><b id='PiSjD'><form id='PiSjD'><ins id='PiSjD'></ins><ul id='PiSjD'></ul><sub id='PiSjD'></sub></form><legend id='PiSjD'></legend><bdo id='PiSjD'><pre id='PiSjD'><center id='PiSjD'></center></pre></bdo></b><th id='PiSjD'></th></span></q></dt></tr></i><div id='PiSjD'><tfoot id='PiSjD'></tfoot><dl id='PiSjD'><fieldset id='PiSjD'></fieldset></dl></div>
      3. Python子进程超时终止

        时间:2023-07-21
        • <legend id='vebBr'><style id='vebBr'><dir id='vebBr'><q id='vebBr'></q></dir></style></legend>

          <small id='vebBr'></small><noframes id='vebBr'>

            <tbody id='vebBr'></tbody>

            <tfoot id='vebBr'></tfoot>
            <i id='vebBr'><tr id='vebBr'><dt id='vebBr'><q id='vebBr'><span id='vebBr'><b id='vebBr'><form id='vebBr'><ins id='vebBr'></ins><ul id='vebBr'></ul><sub id='vebBr'></sub></form><legend id='vebBr'></legend><bdo id='vebBr'><pre id='vebBr'><center id='vebBr'></center></pre></bdo></b><th id='vebBr'></th></span></q></dt></tr></i><div id='vebBr'><tfoot id='vebBr'></tfoot><dl id='vebBr'><fieldset id='vebBr'></fieldset></dl></div>
              <bdo id='vebBr'></bdo><ul id='vebBr'></ul>
                • 本文介绍了Python子进程超时终止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  我正在 python 中使用 subprocess 模块运行一些 shell 脚本.如果 shell 脚本运行时间过长,我喜欢终止子进程.我认为如果我将 timeout=30 传递给我的 run(..) 语句就足够了.

                  I am running some shell scripts with the subprocess module in python. If the shell scripts is running to long, I like to kill the subprocess. I thought it will be enough if I am passing the timeout=30 to my run(..) statement.

                  代码如下:

                  try:
                      result=run(['utilities/shell_scripts/{0} {1} {2}'.format(
                                          self.language_conf[key][1], self.proc_dir, config.main_file)],
                                  shell=True,
                                  check=True,
                                  stdout=PIPE,
                                  stderr=PIPE, 
                                  universal_newlines=True, 
                                  timeout=30,
                                  bufsize=100)
                  except TimeoutExpired as timeout:
                  

                  我已经用一些运行 120 秒的 shell 脚本测试了这个调用.我预计子进程会在 30 秒后被杀死,但实际上该进程正在完成 120 秒脚本,然后引发超时异常.现在的问题是如何通过超时杀死子进程?

                  I have tested this call with some shell scripts that runs 120s. I expected the subprocess to be killed after 30s, but in fact the process is finishing the 120s script and than raises the Timeout Exception. Now the Question how can I kill the subprocess by timeout?

                  推荐答案

                  文档明确指出应该终止进程:

                  The documentation explicitly states that the process should be killed:

                  来自 subprocess.run 的文档:

                  from the docs for subprocess.run:

                  将超时参数传递给Popen.communicate().如果超时,子进程将被杀死并等待.子进程终止后将重新引发TimeoutExpired异常."

                  "The timeout argument is passed to Popen.communicate(). If the timeout expires, the child process will be killed and waited for. The TimeoutExpired exception will be re-raised after the child process has terminated."

                  但在您的情况下,您使用的是 shell=True,我之前也看到过类似的问题,因为阻塞进程是 shell 进程的子进程.

                  But in your case you're using shell=True, and I've seen issues like that before, because the blocking process is a child of the shell process.

                  如果您正确分解参数并且您的脚本具有正确的 shebang,我认为您不需要 shell=True.你可以试试这个:

                  I don't think you need shell=True if you decompose your arguments properly and your scripts have the proper shebang. You could try this:

                  result=run(
                    [os.path.join('utilities/shell_scripts',self.language_conf[key][1]), self.proc_dir, config.main_file],  # don't compose argument line yourself
                              shell=False,  # no shell wrapper
                              check=True,
                              stdout=PIPE,
                              stderr=PIPE, 
                              universal_newlines=True, 
                              timeout=30,
                              bufsize=100)
                  

                  请注意,我可以很容易地在 Windows 上重现此问题(使用 Popen,但它是同一件事):

                  note that I can reproduce this issue very easily on Windows (using Popen, but it's the same thing):

                  import subprocess,time
                  
                  p=subprocess.Popen("notepad",shell=True)
                  time.sleep(1)
                  p.kill()
                  

                  => 记事本保持打开状态,可能是因为它设法与父 shell 进程分离.

                  => notepad stays open, probably because it manages to detach from the parent shell process.

                  import subprocess,time
                  
                  p=subprocess.Popen("notepad",shell=False)
                  time.sleep(1)
                  p.kill()
                  

                  => 记事本在 1 秒后关闭

                  => notepad closes after 1 second

                  有趣的是,如果你删除 time.sleep()kill() 甚至可以使用 shell=True 可能是因为它成功杀死了正在启动 notepad.

                  Funnily enough, if you remove time.sleep(), kill() works even with shell=True probably because it successfully kills the shell which is launching notepad.

                  我并不是说您有完全相同的问题,我只是证明 shell=True 出于多种原因是邪恶的,并且无法终止/超时该进程是另一个原因原因.

                  I'm not saying you have exactly the same issue, I'm just demonstrating that shell=True is evil for many reasons, and not being able to kill/timeout the process is one more reason.

                  但是,如果你需要shell=True是有原因的,你可以使用psutil最后杀死所有的孩子.在这种情况下,最好使用 Popen 直接获取进程 ID:

                  However, if you need shell=True for a reason, you can use psutil to kill all the children in the end. In that case, it's better to use Popen so you get the process id directly:

                  import subprocess,time,psutil
                  
                  parent=subprocess.Popen("notepad",shell=True)
                  for _ in range(30): # 30 seconds
                      if parent.poll() is not None:  # process just ended
                        break
                      time.sleep(1)
                  else:
                     # the for loop ended without break: timeout
                     parent = psutil.Process(parent.pid)
                     for child in parent.children(recursive=True):  # or parent.children() for recursive=False
                         child.kill()
                     parent.kill()
                  

                  (来源:如何杀死进程和子进程蟒蛇?)

                  该示例也杀死了记事本实例.

                  that example kills the notepad instance as well.

                  这篇关于Python子进程超时终止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  上一篇:如何使用 python 在多个终端窗口中运行多个文件 下一篇:gpg --passphrase-fd 不适用于 python 3 子进程

                  相关文章

                  <small id='RBjfe'></small><noframes id='RBjfe'>

                  <tfoot id='RBjfe'></tfoot>
                    1. <legend id='RBjfe'><style id='RBjfe'><dir id='RBjfe'><q id='RBjfe'></q></dir></style></legend>
                      <i id='RBjfe'><tr id='RBjfe'><dt id='RBjfe'><q id='RBjfe'><span id='RBjfe'><b id='RBjfe'><form id='RBjfe'><ins id='RBjfe'></ins><ul id='RBjfe'></ul><sub id='RBjfe'></sub></form><legend id='RBjfe'></legend><bdo id='RBjfe'><pre id='RBjfe'><center id='RBjfe'></center></pre></bdo></b><th id='RBjfe'></th></span></q></dt></tr></i><div id='RBjfe'><tfoot id='RBjfe'></tfoot><dl id='RBjfe'><fieldset id='RBjfe'></fieldset></dl></div>

                      • <bdo id='RBjfe'></bdo><ul id='RBjfe'></ul>