当通过python的subprocess模块调用一个Linux二进制文件需要相当长的时间时,这会释放gil吗?
我想并行处理一些从命令行调用二进制程序的代码。使用线程(通过threading和multiprocessing.pool.ThreadPool还是multiprocessing更好?我的假设是,如果subprocess发行了gil,那么选择threading选项更好。
- 请澄清。目前的答案认为,您担心的是孩子进程本身以某种方式持有gil,但我认为您可能担心subprocess.call()或subprocess.Popen(...).wait()会阻塞调用方的其他线程。(他们没有。)
- @Pilcrow:作为一个从谷歌看到这个问题的人,我建议你把你的评论变成一个答案,因为与现有答案不同,它解决的是实际的问题。
- @R&246;RD:我已经这样做了,谢谢。
When calling a linux binary which takes a relatively long time through Python's subprocess module, does this release the GIL?
号
是的,它在调用过程中释放全局解释器锁(gil)。
正如您可能知道的,在POSIX平台上,subprocess在fork、execve和waitpid的"原始"组件上提供了方便的接口。
通过对cpython 2.7.9来源的检查,fork和execve不释放gil。但是,这些电话不会阻塞,所以我们不希望GIL被释放。
当然,waitpid确实会阻塞,但我们看到它的实现确实放弃了使用allow_threads宏的gil:
1 2 3 4 5 6 7 8
| static PyObject *
posix_waitpid(PyObject *self, PyObject *args)
{
....
Py_BEGIN_ALLOW_THREADS
pid = waitpid(pid, &status, options);
Py_END_ALLOW_THREADS
.... |
。
这也可以通过从演示的多线程Python脚本中调用一些长时间运行的程序(如sleep)来测试。
- 作为一个规则的头部,吉尔在CPython发布使用阻塞操作系统API,如waitpid()。。。。。。。这是什么意思的特异性的方法,从subprocess模块。注:execve()obviosly块(在孩子在叉在这个案例),它是只读文件时返回错误。fork()是一个特殊的案例:"读这样的讨论来了解为什么你应该避免混合的多线程和fork()(fork()immidiately followed用exec()是精细)。
- "是的j.f.sebastian:回复:不规则的头部和dangers系混合线程和福克斯。我会对问题的表征execve()为"阻塞",但是。。。。。。。一个成功的execve不T形块的来电,它vaporizes的来电。
gil不跨越多个进程。subprocess.Popen开始了一个新的过程。如果它启动了一个python进程,那么它将拥有自己的gil。
如果只想并行运行一些Linux二进制文件,则不需要多个线程(或由multiprocessing创建的进程):
1 2 3 4 5 6 7 8 9
| from subprocess import Popen
# start all processes
processes = [Popen(['program', str(i)]) for i in range(10)]
# now all processes run in parallel
# wait for processes to complete
for p in processes:
p.wait() |
您可以使用multiprocessing.ThreadPool来限制并发运行的程序的数量。
- 应该是multiprocessing.Pool
- "danqiwang:好的。multiprocessing提供纸的工艺为基础的游泳池和一个基于线程池与编号接口。都可以用depending是环境特征。
- 我不明白为什么你有一个倾斜的大学TheadPoolpool过这里。pool也能限制数和并发运行的进程将不会suffer从吉尔。此外,ThreadPooldocumented是难的。
- "danqiwang:教皇开始新工艺;这是好的,吉尔问题作为第一款的规定,在回答说。你可以使用from multiprocessing.dummy import Pool(同样的事情作为ThreadPool),那么你需要改变你的代码中使用线程的使用过程是℃.dummy从进出。该接口是编号。
- understood。。。。。。。不注意,它的Popen。。。。。。。我的坏了。谢谢,诠释的方法。
- 这不会工作,如果你需要发送数据的过程或检索的产出。的方法,你需要使用通信(等待)这一工艺的Terminate方法。
- "t3rm1错误。1的代码在回答厂AS IS。2在这里的如何适应它,to get产出过程,从多concurrently。。。。。。。虽然它有什么做与吉尔(这是释在阻塞I / O操作)
由于subprocess用于运行可执行文件(本质上是围绕os.fork()和os.execve()的包装),因此使用它可能更有意义。您可以使用subprocess.Popen。比如:
1 2 3
| import subprocess
process = subprocess.Popen(["binary"]) |
号
这将作为一个单独的过程运行,因此不受GIL的影响。然后,可以使用Popen.poll()方法检查子进程是否已终止:
1 2 3
| if process.poll():
# process has finished its work
returncode = process.returncode |
只需要确保不调用等待进程完成其工作的任何方法(例如popen.communication()),以避免您的python脚本阻塞。
如本答案所述
multiprocessing is for running functions within your existing
(Python) code with support for more flexible communications among the
family of processes. multiprocessing module is intended to provide
interfaces and features which are very similar to threading while
allowing CPython to scale your processing among multiple CPUs/cores
despite the GIL.
号
因此,考虑到您的用例,subprocess似乎是正确的选择。
- process.stdout.readlines()5块,如果任何国家的任何子进程的填补他们的stderr缓冲管。如果你想读两stdout和stderr separately,那么你需要的异步方法:线程或无阻塞的管道或IOCP是Windows
- 绝对的权利!被遗忘的我有什么说的。谢谢。。。。。。。