为啥 Python 子进程“继承”父进程的线程?
Posted
技术标签:
【中文标题】为啥 Python 子进程“继承”父进程的线程?【英文标题】:Why does Python subprocess "inherit" the threads from the parent process?为什么 Python 子进程“继承”父进程的线程? 【发布时间】:2021-12-31 02:40:39 【问题描述】:我是 Python 3 multiprocessing
模块的新手,可能似乎误解了其中的一个概念。在我的应用程序中,像往常一样,我有一个主线程,还有另一个用于一些“后台”工作的线程,称为“BgThread”。从第二个线程我生成了一个Process
并通过start()
运行它。
新的子进程现在可以正确启动并开始工作了。但是,当我在(VS Code)调试器中查看我的应用程序时,我可以看到这个子进程也运行着第二个线程,也称为“BgThread”。
在 Linux 上运行我尝试通过 mp.set_start_method("spawn")
生成线程,如多处理文档中所述,但结果相同。此外,当我在我的第二个线程类的run()
方法中设置断点时,在子进程中它不会在那里停止(但在主进程中它是正确的)。
这是正常行为吗?如果是这样,那么我不明白 - 为什么子进程也从其父进程继承第二个线程,即使它似乎并没有真正通过它再次启动它,如上所述?是否需要阻止我的子进程再次启动第二个线程?
【问题讨论】:
你屏蔽了if __name__ == "__main__":
的多处理吗?
看起来调试器的行为不正确。我会尝试调查htop
/top
/ps
@Timus 这是一个 Flask 应用程序,是的,我确实在其 run.py
文件中使用了 if
语句。我还定义了通过multiprocessing.set_start_method("spawn")
生成子进程,而不是分叉它。
【参考方案1】:
正如@AndriiMaletskyi 评论的那样,您所看到的一定是您的调试器引入的一些奇怪结果。以下程序在 Linux 下运行,使用spawn
启动新进程,首先创建一个线程,然后启动一个进程。该线程被传递了一个multiprocessing.Value
实例,该实例在一个循环中递增5 次,在该循环中它还打印出一条消息。如果子进程继承了这个线程,我们希望看到打印出超过 5 条消息,并且这个 multiprocessing.Value
实例的最终值大于 5。此外,为了更好地衡量,子进程枚举了它的线程并且只有一个。如果它从主进程继承了线程,那么如果不是三个,那么至少会有两个。
from multiprocessing import Process, Value, set_start_method
from os import getpid
import threading
import time
def worker(*args):
first_time = True
for x, y in args:
time.sleep(1.1)
print(f'x + y = x + y')
if first_time:
first_time = False
for thread in threading.enumerate():
print('thread:', thread.name)
def my_thread(v):
for counter in range(1, 6):
print(f'time: time.time(), counter: counter, process id: getpid(), thread id: threading.get_ident()')
with v.get_lock():
v.value += 1
time.sleep(1)
if __name__ == '__main__':
set_start_method("spawn")
v = Value('i', 0, lock=True)
t = threading.Thread(target=my_thread, args=(v,))
t.start()
args = ((1, 2), (3, 4), (4, 5), (6,7))
p = Process(target=worker, args=args)
p.start()
p.join()
t.join()
print('Value =', v.value)
打印:
time: 1637499015.9222672, counter: 1, process id: 33, thread id: 139689716135680
time: 1637499016.9244416, counter: 2, process id: 33, thread id: 139689716135680
1 + 2 = 3
thread: MainThread
time: 1637499017.925643, counter: 3, process id: 33, thread id: 139689716135680
3 + 4 = 7
time: 1637499018.926832, counter: 4, process id: 33, thread id: 139689716135680
4 + 5 = 9
time: 1637499019.9280066, counter: 5, process id: 33, thread id: 139689716135680
6 + 7 = 13
Value = 5
【讨论】:
以上是关于为啥 Python 子进程“继承”父进程的线程?的主要内容,如果未能解决你的问题,请参考以下文章