等待具有多个并行作业的子进程结束
我正在并行运行 python 中的一些子进程。我想等到每个子进程完成。我正在做一个不优雅的解决方案:
runcodes = ["script1.C", "script2.C"]
ps = []
for script in runcodes:
args = ["root", "-l", "-q", script]
p = subprocess.Popen(args)
ps.append(p)
while True:
ps_status = [p.poll() for p in ps]
if all([x is not None for x in ps_status]):
break
是否有一个类可以处理多个子进程?问题是 wait
方法阻塞了我的程序。
更新:我想显示计算过程中的进度:类似于“4/7 subprocess finish...”
如果您好奇root
编译c ++脚本并执行它。
I'm running some subprocesses from python in parallel. I want to wait until every subprocess have finished. I'm doing a non elegant solution:
runcodes = ["script1.C", "script2.C"]
ps = []
for script in runcodes:
args = ["root", "-l", "-q", script]
p = subprocess.Popen(args)
ps.append(p)
while True:
ps_status = [p.poll() for p in ps]
if all([x is not None for x in ps_status]):
break
is there a class that can handle multiple subprocess? The problem is that the wait
method block my program.
update: I want to show the progress during the computation: something like "4/7 subprocess finished..."
If you are curious root
compile the c++ script and execute it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果您的平台不是 Windows,您可能可以选择子进程的标准输出管道。然后,您的应用程序将阻塞,直到:
使用 epoll 的非充实示例对于 Linux 2.6.xx:
If your platform is not Windows, you could probably select against the stdout pipes of your subprocesses. Your app will then block until either:
Non-fleshed-out example using epoll with Linux 2.6.xx:
怎么样
How about
您可以这样做:
这些进程将并行运行,最后您将等待所有进程。
You could do something like this:
The processes will run in parallel, and you'll wait for all of them at the end.
这个答案与这个答案相关,并在下面使用类似的机制(基于
select
系统调用)称为asyncio
。您可以在此处了解有关
asyncio
的更多信息。当您的进程受 IO 限制时,Asyncio 非常有用。您的进程似乎是 IO 绑定的,至少在程序的这一部分中,花费大部分时间等待外部脚本完成,并且仅在其末尾打印一条消息。
以下代码应该适合您(也许需要一些细微的调整):
一些详细的解释。
Asyncio 允许您通过交替执行各种异步任务并在所有异步任务都被阻塞时简单地等待,从而使用单个线程执行并发任务。
函数
run_script
是异步的,将使用与subprocess.Popen
类似的机制调用您的脚本。这里的区别在于,返回的对象是可等待的,这意味着当等待函数被阻塞时,您可以跳转到其他对象。您可以在此处阅读有关使用
asyncio
进行子流程管理的更多信息< /a>.您会注意到子进程的管理与“正常”Python 子处理非常相似。波彭的论点也类似。请注意,这与线程不同。事实上,这个程序是单线程的。不要将 asyncio 与多线程混淆。它们是同时运行任务的两种不同方法(各有利弊)。
main 函数将创建多个任务,每个任务对应您要运行并等待它们的每个脚本。
重要的是这个
await
不会阻塞,同时也不会进行实时轮询。它将休眠,直到任何任务准备就绪。一旦任务准备就绪,执行就会返回到该任务,该任务可以打印有关您的消息的语句。不过,在所有等待的任务完成之前,程序不会退出主函数。它将停留在由 asyncio.run 生成的等待函数的循环中,直到一切完成。
This answer is related to this answer and uses a similar mechanism underneath (based on the
select
syscall) calledasyncio
.You can read more about
asyncio
here.Asyncio is good when your process is IO-bound. Your process seems to be IO-bound, at least in this section of your program, spending most of its time waiting for the external scripts to complete and only printing a message at their end.
The following code should work for you (with some minor adjustments perhaps):
Some detailed explanation.
Asyncio allows you to execute concurrent tasks with a single thread by alternating the various asynchronous tasks and simply waiting when all of them are blocked.
The function
run_script
is asynchronous and will call your script using a similar mechanism tosubprocess.Popen
. The difference here is that the returning object is awaitable meaning that you can jump to something else while the wait function is blocked.You can read more about subprocess management with
asyncio
here. You will notice the management of the subprocess is very similar to the "normal" Python subprocessing. The arguments of the Popen are also similar.Notice that this is different to threading. In fact, this program is single-threaded. Do not confuse asyncio with multi-threading. They are two different approaches to run tasks concurrently (with pros and cons).
The main function will create multiple tasks, one for each script you want to run and wait on them.
The important thing is that this
await
will not be blocking and at the same time it will not do live-polling. It will sleep until any of the tasks will be ready. Once a task is ready the execution returns to that task that can print a statement about your message.The program will not exit the main function until all awaited tasks are done, though. It will stay within the loop of awaited functions generated by
asyncio.run
until everything is completed.我认为答案不在于 python 代码或语言功能,而在于系统功能,请考虑以下解决方案:
I think the answer is not in python code or language features but it is in the system capabilities , consider this solution :