python - Python 子进程在没有睡眠的情况下无法工作
问题描述
我正在开发一个 Python 启动器,它应该通过调用子进程来执行我列表中的一些程序。代码是正确的,但它的工作方式非常奇怪。
简而言之,如果没有一些sleep或main中的输入命令,它就无法工作。
这是示例:
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 ;)")
但没有输入或睡眠它不起作用:
if __name__ == '__main__':
# Doesn't work
main()
请有人解释一下,为什么会这样?
我有一些想法,但我不确定。也许是因为子进程是异步的,程序在子进程执行之前执行并关闭自己。
在sleep和input的情况下,程序暂停并且子进程有足够的时间执行。
谢谢你的帮助!
解决方案
一旦最后一个线程开始,你的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()
推荐阅读
- python - 使用 h5py 高效访问 HDF5 属性
- r - 按组对变量求和并将其作为新变量添加到数据框中
- swiftui - SwiftUI:在带有 SidebarListStyle 的 NavigationView / List 中选择 NavigationLink
- oracle - 编写一个 PL/SQL 代码来计算数字(1-10)的 2 的幂?
- deep-learning - 用于实例分割的极简 coco 数据集:无法创建合法的数据集
- c - C中的字符串处理问题
- bash - Bash中的关联数组-带点的键的问题
- ansible - 使用 ansible playbook 检查嵌套数据结构中的给定字符串
- reactjs - 发布请求中 JSON 输入意外结束
- docusignapi - 在此处签名选项卡仅适用于一位签名者