我有一个Python 3.7项目
它使用的库使用子进程Popen
调用Shell脚本。
我想知道:如果将库调用放在单独的线程中,我可以在等待另一个线程中Popen
的结果的同时在主线程中工作吗?
https://stackoverflow.com/a/33352871/202168这里有一个答案:
Python线程与GIL一起工作的方式是使用一个简单的计数器。 每执行100个字节代码,应该释放GIL 由当前正在执行的线程提供给其他线程 有机会执行代码。此行为在Python中基本上已被破坏 2.7由于线程释放/获取机制。它已在Python 3中修复。
对于我想做的事情,两种方法听起来都不是特别希望。听起来好像如果在调用Popen.wait
时“库调用”线程未达到100字节码触发点,则可能不会切换到我的其他线程,整个应用程序将等待子进程? / p>
但是,此信息可能是错误的。
这里是另一个答案https://stackoverflow.com/a/16262657/202168,其中说:
...解释器可以始终释放GIL;它会给一些 解释了足够的指令后的其他线程,或者 如果执行某些I / O,则自动执行。请注意,自从最近的Python 3.x开始, 准则不再基于执行的数量 指示,但是否有足够的时间。
这听起来更有希望,因为大概与子进程进行通信将涉及I / O,因此可能允许我的主线程在此期间进行上下文切换。 (或者只是经过wait
的等待时间会导致上下文切换)
我知道https://docs.python.org/3/library/asyncio-subprocess.html可以解决此问题,但是我正在调用仅使用简单subprocess.Popen
的第三方库。
任何人都可以确认“子进程在单独的线程中调用”的想法是否可能对我有用,特别是在Python 3.7中?
答案 0 :(得分:0)
我有时间做实验,所以我会回答我自己的问题...
我设置了两个文件:
mainthread.py
#!/usr/bin/env python
import subprocess
import threading
import time
def run_busyproc():
print(f'{time.time()} Starting busyprocess...')
subprocess.run(["python", "busyprocess.py"])
print(f'{time.time()} busyprocess done.')
if __name__ == "__main__":
thread = threading.Thread(target=run_busyproc)
print("Starting thread...")
thread.start()
while thread.is_alive():
print(f"{time.time()} Main thread doing its thing...")
time.sleep(0.5)
print("Thread is done (?)")
print("Exit main.")
和busyprocess.py
:
#!/usr/bin/env python
from time import sleep
if __name__ == "__main__":
for _ in range(100):
print("Busy...")
sleep(0.5)
print("Done")
从命令行运行mainthread.py
,我可以看到有一个上下文切换,您希望看到它-主线程能够在等待子进程的结果的同时工作:
Starting thread...
1555970578.20475 Main thread doing its thing...
1555970578.204679 Starting busyprocess...
Busy...
1555970578.710308 Main thread doing its thing...
Busy...
1555970579.2153869 Main thread doing its thing...
Busy...
1555970579.718168 Main thread doing its thing...
Busy...
1555970580.2231748 Main thread doing its thing...
Busy...
1555970580.726122 Main thread doing its thing...
Busy...
1555970628.009814 Main thread doing its thing...
Done
1555970628.512945 Main thread doing its thing...
1555970628.518155 busyprocess done.
Thread is done (?)
Exit main.
大家好消息,python线程有效:)