多进程还是使用 os.fork 和 os.exec?

4 投票
2 回答
6496 浏览
提问于 2025-04-17 14:47

我正在使用多进程模块来创建子进程。因为在创建子进程时,子进程会继承父进程的地址空间,所以我发现父进程和子进程使用的是同一个日志记录器。我想要清除子进程中从父进程继承过来的任何值。我了解到多进程模块在底层使用的是fork(),但并没有使用exec()。我想知道在我的情况下使用多进程是否合适,还是应该使用os.fork()和os.exec()的组合,或者有没有其他解决方案?

谢谢。

2 个回答

3

你可以在子进程中重新绑定日志记录器,让它使用自己的。关于其他操作系统我不太清楚,但在Linux上,创建子进程并不会复制整个内存空间(正如Ellioh提到的),而是使用了“写时复制”的概念。也就是说,直到你在子进程中修改了什么,它的内存内容仍然是父进程的内容。例如,你可以创建100个子进程(这些子进程只读取,不写入内存),然后检查整体的内存使用情况。这样的话,内存使用量不会是parent_memory_usage * 100,而是要少得多。

8

因为 multiprocessing 是在你的程序中运行一个函数,就像它是一个线程函数一样,所以它需要完整复制你程序的状态。这就需要用到 fork() 这个操作。

通常来说,使用 multiprocessing 提供的更高级的接口会更好。至少你不需要自己去关心 fork() 的返回结果。

os.fork() 是一个较低级的函数,提供的服务比较少,不过你当然可以用它来做任何 multiprocessing 能做的事情……但这样你就得部分重新实现 multiprocessing 的代码。所以,我觉得 multiprocessing 对你来说应该是可以的。

不过,如果你程序的内存占用太大,无法复制(或者你有其他原因想避免使用 fork,比如打开的数据库连接、日志文件等等),你可能需要把想要在新进程中运行的函数做成一个单独的 Python 程序。然后你可以用 subprocess 来运行它,传递参数给它的 stdin,捕获它的 stdout,并解析输出以获取结果。

更新: os.exec... 一系列函数 对于大多数用途来说比较难用,因为它会用一个新的进程替换掉你的进程(如果你运行的程序和当前运行的程序是一样的,它会从头开始,不会保留任何内存中的数据)。不过,如果你真的不需要继续执行父进程,exec() 可能会有一些用处。

根据我的个人经验:在 Unix 系统上,os.fork() 经常被用来创建守护进程;我经常使用 subprocess(通过 stdin/stdout 进行通信);几乎从来没有用过 multiprocessing;我一生中没有一次需要用到 os.exec...()

撰写回答