Python子进程在没有睡眠的情况下无法工作

时间:2019-08-17 11:06:16

标签: python asynchronous subprocess launch

我正在开发一个Python启动器,该启动器应通过调用子进程来执行列表中的一些程序。该代码是正确的,但是却很奇怪。

简而言之,如果没有 main 中的某些 sleep input 命令,该命令将不起作用。

这里是示例:

import threading
import subprocess
import time

def executeFile(file_path):
  subprocess.call(file_path, shell=True)


def main():
  file = None

  try:
      file = open('./config.ini', 'r');
  except:
    # TODO: add alert widget
    print("cant find a file")

  pathes = [ path.strip() for path in file.readlines() ]

  try:
    for idx in range(len(pathes)):
        print(pathes[idx])
        file_path = pathes[idx];
        newThread = threading.Thread(target=executeFile, args=(file_path,))
        newThread.daemon = True
        newThread.start()
  except:
    print("cant start thread")


  if __name__ == '__main__':
    main()

    # IT WORKS WHEN SLEEP EXISTS
    time.sleep(10)

    # OR
    # input("Press enter to exit ;)")

但没有 input sleep 则不起作用:

if __name__ == '__main__':
   # Doesn't work
   main()

有人可以解释一下,为什么会发生?

我有个主意,但不确定。可能是因为 subprocess 是异步的,并且该程序在子流程执行之前执行并关闭了自身。

如果 sleep input ,程序将挂起,并且子进程有足够的时间执行。

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

最后一个线程启动后,您的main()返回。依次退出您的Python程序。那会停止所有线程。

来自守护程序线程的文档:

  

注意:守护程序线程在关闭时突然停止。它们的资源(例如打开的文件,数据库事务等)可能无法正确释放。如果希望线程正常停止,请使其成为非守护进程,并使用适当的信号机制,例如事件。

简单的解决方法是使用守护程序线程。


顺便说一句,我建议您对循环进行一些更改。首先,直接遍历pathes而不是使用索引。第二;分别捕获每个线程的错误,因此一个错误不会导致剩余文件未被处理。

for path in pathes:
    try:
        print(path)
        newThread = threading.Thread(target=executeFile, args=(path,))
        newThread.start()
    except:
        print("cant start thread for", path)

另一种选择是完全跳过线程,仅维护正在运行的子进程的列表:

import os
import subprocess
import time


def manageprocs(proclist):
    """Check a list of subprocesses for processes that have
       ended and remove them from the list.

    :param proclist: list of Popen objects
    """
    for pr in proclist:
        if pr.poll() is not None:
            proclist.remove(pr)
    # since manageprocs is called from a loop,
    # keep CPU usage down.
    time.sleep(0.5)


def main():

    # Read config file
    try:
        with open('./config.ini', 'r') as f:
            pathes = [path.strip() for path in f.readlines()]
    except FileNotFoundError:
        print("cant find config file")
        exit(1)

    # List of subprocesses
    procs = []
    # Do not launch more processes concurrently than your
    # CPU has cores.  That will only lead to the processes
    # fighting over CPU resources.
    maxprocs = os.cpu_count()
    # Launch all subprocesses.
    for path in pathes:
        while len(procs) == maxprocs:
            manageprocs(procs)
        procs.append(subprocess.Popen(path, shell=True))
    # Wait for all subprocesses to finish.
    while len(procs) > 0:
        manageprocs(procs)


if __name__ == '__main__':
    main()
相关问题