如何使用Python2.7.10中的多处理来创建子过程,而没有孩子与父母共享资源



我们正在尝试将python 2.7.10代码库从Windows移动到Linux。我们最近发现,Python 2.7中的多处理库在Windows与Linux上的行为不同。我们发现许多这样的文章描述了这个问题,但是我们无法在线找到Python 2.7的解决方案。这是在Python 3.4中解决此问题的解决方案,但是,我们无法升级到Python 3.4。有什么方法可以在Linux上使用Python 2.7中使用多处理,而没有孩子和父母共享内存?我们还可以在Python 2.7中使用指导来修改叉车代码,以确保子和父程进程不共享内存并进行复印件。谢谢!

一个可能的解决方案是使用loky,该库在python2.7中提供了用fork-exec实现的Processfork-exec启动方法的行为与Spawn相似,在新生成的过程中具有新的解释器。该库主要设计用于提供concurrent.futures API,但您可以使用mp = loky.backend.get_context()获得与multiprocessing相同的API。

from loky.backend import get_context
import multiprocessing as mp

def child_without_os():
    print("Hello from {}".format(os.getpid()))

def child_with_os():
    import os
    print("Hello from {}".format(os.getpid()))

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser('Test loky backend')
    parser.add_argument('--use-fork', action="store_true",
                        help="Use start_method='fork' instead of 'loky'")
    parser.add_argument('--with-os', action="store_true",
                        help='Import os module in the child interpreter')
    args = parser.parse_args()
    # Only import os in the main module, this should fail if the interpreter is
    # not shared
    import os
    print("Main is {}".format(os.getpid()))
    if args.use_fork:
        ctx = mp
        print("Using fork context")
    else:
        ctx = get_context('loky_init_main')
        print("Using loky context")
    if args.with_os:
        target = child_with_os
    else:
        target = child_without_os
    p = ctx.Process(target=target)
    p.start()
    p.join()

这给出

# Use the default context, the child process has a copy-on-write interpreter
# state and can use the os module.
$ python2 test.py --use-fork
Main is 14630
Using fork context
Hello from 14633

# Use the loky context, the child process has a fresh interpreter
# state and need to import the os module.
$ python2 test.py
Main is 14661
Using loky context
Process LokyInitMainProcess-1:
Traceback (most recent call last):
  File "/usr/lib/python2.7/multiprocessing/process.py", line 267, in _bootstrap
    self.run()
  File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
    self._target(*self._args, **self._kwargs)
  File "/home/tom/Work/prog/loky/test.py", line 6, in child_without_os
    print("Hello from {}".format(os.getpid()))
NameError: global name 'os' is not defined

# Now using the correct child function which import the os module
$ python2 test.py --with-os
Main is 14700
Using loky context
Hello from 14705

(免责声明:我是loky的维护者之一)。

毫无疑问,cpython bug跟踪器中的补丁程序不会干净地应用于Python 2.7的多处理版本,并且这些补丁包含semaphore.c的一些额外功能,因此此后,将信号量正确清理。

我认为您最好的选择是从Python 3中退出多处理模块。复制Python代码,将其重命名为processing,发现丢失的C功能并围绕它们工作(例如,清理您自己的邮件机或Don''t使用它们)。尽管库很大,但仅移植您使用的功能可能很简单。如果您能够发布Backport,我确定许多人会对该项目感兴趣。

取决于您对多处理的严重依赖,另一种选择是通过使用subprocess模块运行sys.executable来运行更多的python。

最新更新