【问题标题】:Removing daemon from python multiprocessing process从 python 多处理进程中删除守护进程
【发布时间】:2018-06-10 15:15:27
【问题描述】:

使用 python 3.6,我遇到了这样的问题:(1) 在令人尴尬的并行作业上有一个 joblib.Parallel 循环 (2) 作业本身是相当耗时的 c++ 本机对象,偶尔会出现段错误并且我无法修改其代码。

为了防止出现段错误,我尝试将作业本身包装在一个多处理进程中。不幸的是,使用此解决方案,python 本身会使用daemonic processes are not allowed to have children 引发断言错误。

所以我采用了此处发布的解决方案并尝试从 Process 继承:https://stackoverflow.com/a/8963618/614684

这也不起作用,所以我想出了以下可行的解决方案:

class NoDaemonProcess(multiprocessing.Process):
  def __init__(self, group=None, target=None, name=None, args=(), kwargs={},
               *, daemon=None):
    super(NoDaemonProcess, self).__init__(group, target, name, args, kwargs, daemon=daemon)
    if 'daemon' in multiprocessing.process._current_process._config:
      del multiprocessing.process._current_process._config['daemon']
    self._config = multiprocessing.process._current_process._config.copy()
  # make 'daemon' attribute always return False                                                                                                                                              
  def _get_daemon(self):
    return False
  def _set_daemon(self, value):
    pass
  daemon = property(_get_daemon, _set_daemon)

基本上,我修改了多处理包的全局状态,以删除当前进程是守护进程这一事实。

有没有更好的方法来做到这一点?我将不胜感激任何有助于使其更强大和可靠的帮助。

【问题讨论】:

标签: python python-multiprocessing


【解决方案1】:

保持简单,愚蠢:)

您的错误消息位于https://github.com/python/cpython/blob/master/Lib/multiprocessing/process.py#L110

您可以使用常规的subprocess 作为工作负载的一部分。它不受任何multiprocessing 逻辑的约束。为了避免专门为此创建一个单独的 Python 程序,只需这样做

subprocess.Popen([sys.executable,__file__,"<arg>"])

并使&lt;arg&gt; 触发if __name__ == '__main__' 块中的必要逻辑。

要从子进程中获取结果,可以以任何机器可读格式将其打印到标准输出,或使用任何 IPC 机制。

【讨论】:

  • 我知道错误消息的来源。我通过查看多处理源得出了我的解决方案。子进程将不起作用。这项工作是通过 c++ 库提供的,其访问权限是通过 cython 提供的。这不是命令行调用。
  • @JasonMond 您可以使用命令行参数启动同一个 Python 文件,该参数将触发 if __name__ == '__main__' 块中的必要逻辑。
  • 那也无济于事。作业的许多参数之一是 xml 对象列表。可以是 100 MB 的数量级。除了将这些文件写入空间非常宝贵的文件系统(并且我有 1000 多个这样的作业并行运行)之外,我看不到这些东西如何以干净的方式通过子进程作为参数传递。然后返回值是在 cython 中创建的结构化 python 对象。我可能可以创建一个基于 json 的序列化和反序列化函数,以便它可以通过子进程,但这也是相当多的工作。
  • @JasonMond 一样,stdin 或 IPC。 multiprocessing 在底层使用 pickle,所以它就像在另一端的 pickle.dump(args,process.stdin).load(sys.stdin) 一样简单(sys.stdin.buffer 在 Py3 中以二进制模式读取)。
  • @JasonMond 如果你使用 fork,你根本不需要发送输入数据,只需要返回结果。
猜你喜欢
  • 2023-03-10
  • 2011-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多