我的问题是我有一个父进程A,并且我设置了一个守护进程线程作为RPC服务器,如TaskRPCServer(Thread(。然后我想使用 Python 多处理生成一个子进程。进程对象。例如: B = Process((, B.start((.Dese B 将具有与 A 相同的守护进程线程吗? 有没有办法强制 B 不让守护程序线程在 A 中运行? 因为在某些情况下,很多进程会侦听 RPC 端口。或者如果我的设计是错误的,我怎样才能正确地做到这一点? 谢谢!
当你分叉一个孩子时,它只从一个线程开始。这是由POSIX:1定义的
应使用单个线程创建进程。如果多线程进程调用 fork((,则新进程应包含调用线程的副本及其整个地址空间,可能包括互斥锁和其他资源的状态。
因此,子进程将没有守护程序线程。你不必做任何事情来强迫它不要这样做。
您可以自己轻松测试:
import threading
import os
import time
def threadfunc():
while True:
print(os.getpid())
time.sleep(1)
def main():
t = threading.Thread(target=threadfunc)
t.start()
pid = os.fork()
if pid:
print(f'Forked {pid}; sleep time')
time.sleep(5)
else:
print(f'Forked child; sleep time')
time.sleep(5)
main()
如果你运行这个,你会看到这样的内容:
12345
Forked 12346; sleep time
Forked child; sleep time
12345
12345
12345
请注意,守护程序线程打印了 12345(父进程的 PID(5 次,并且没有人打印过 12346(子进程的 PID(。
但与此同时,即使您询问的问题不存在,有时也会在混合fork
和线程时出现问题,multiprocessing
为您提供了解决这些问题的方法,如上下文和启动方法中所述。
multiprocessing.set_start_method('forkserver')
保证子进程从线程、互斥锁等干净状态启动2,还可以防止意外共享文件句柄。(第三个选项,spawn
,通常只有在你想确保你的代码在Unix和Windows上运行相同时才需要。
1. 对于一些非常古老的 Unix 平台来说,这可能不是真的,但对于任何支持 POSIX 线程的 macOS、Linux、*BSD 等来说都是如此,至少可以追溯到 2004 年,可能更早,但我在任何地方都找不到免费且合法的旧 POSIX/SUS 规范......
2. 除了 POSIX 文档警告的问题之外,还有一些更模糊的问题,比如尝试运行 Cocoa 主循环,同时从后台线程进行多处理。