我正在开发一个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 ,程序将挂起,并且子进程有足够的时间执行。
感谢您的帮助!
答案 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()