多进程还是使用 os.fork 和 os.exec?
我正在使用多进程模块来创建子进程。因为在创建子进程时,子进程会继承父进程的地址空间,所以我发现父进程和子进程使用的是同一个日志记录器。我想要清除子进程中从父进程继承过来的任何值。我了解到多进程模块在底层使用的是fork(),但并没有使用exec()。我想知道在我的情况下使用多进程是否合适,还是应该使用os.fork()和os.exec()的组合,或者有没有其他解决方案?
谢谢。
2 个回答
你可以在子进程中重新绑定日志记录器,让它使用自己的。关于其他操作系统我不太清楚,但在Linux上,创建子进程并不会复制整个内存空间(正如Ellioh提到的),而是使用了“写时复制”的概念。也就是说,直到你在子进程中修改了什么,它的内存内容仍然是父进程的内容。例如,你可以创建100个子进程(这些子进程只读取,不写入内存),然后检查整体的内存使用情况。这样的话,内存使用量不会是parent_memory_usage * 100
,而是要少得多。
因为 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...()
。