首页 > 解决方案 > Python3,多处理模块在不同环境下的行为

问题描述

我有以下代码并尝试在 Linux 和 Windows 上运行。在 Linux 上,代码运行良好,但在 Windows 上给了我一个运行时错误。我也尝试在在线编译器上运行代码,代码运行得非常好。

这个问题在某种程度上与self关键字有关。

我没有任何 Apple 产品,如果有人可以在 Mac OS 上运行它会很有帮助。

提前谢谢了。

环境:

 class A:
    def __init__(self):

      # ==== case 1 =====
      # Ubuntu: ok, Windows: ok
      a = multiprocessing.Process(target=self.t, args=())
      a.start()
      a = multiprocessing.Process(target=self.t, args=())
      a.start()
      # ================

      # ==== case 2 ====
      # Ubuntu: ok, Windows: ok
      self.b = multiprocessing.Process(target=self.t, args=())
      self.b.start()
      self.b = multiprocessing.Process(target=self.t, args=())
      self.b.start()
      # ================

      # ==== case 3 ====
      # Ubuntu: ok, Windows: Runtime Error
      c = multiprocessing.Process(target=self.t, args=())
      c.start()
      self.d = multiprocessing.Process(target=self.t, args=())
      self.d.start()
      # ================

      # ==== case 4 ====
      # Ubuntu: ok, Windows: ok
      self.e = multiprocessing.Process(target=self.t, args=())
      self.e.start()
      f = multiprocessing.Process(target=self.t, args=())
      f.start()
      # ================

      # ==== case 5 ====
      # Ubuntu: ok, Windows: Runtime Error
      self.g = [multiprocessing.Process(target=self.t, args=()) for _ in range(2)]
      for proc in self.g:
          proc.start()
      # ================

      # ==== case 6 ====
      # Ubuntu: ok, Windows: ok
      h = [multiprocessing.Process(target=self.t, args=()) for _ in range(2)]
      for proc in h:
          proc.start()
      # ================

      time.sleep(1) 

    def t(self):
        print("Hi")


if __name__ == "__main__":
    A()

单独运行案例 5时 Python 在 Windows 上给出的错误。

Traceback (most recent call last):
  File ".\GeneralUse.py", line 52, in <module>
    A()
  File ".\GeneralUse.py", line 42, in __init__
    proc.start()
  File "C:\Program Files\Python3\lib\multiprocessing\process.py", line 121, in start
    self._popen = self._Popen(self)
  File "C:\Program Files\Python3\lib\multiprocessing\context.py", line 224, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "C:\Program Files\Python3\lib\multiprocessing\context.py", line 326, in _Popen
    return Popen(process_obj)
  File "C:\Program Files\Python3\lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__
    reduction.dump(process_obj, to_child)
  File "C:\Program Files\Python3\lib\multiprocessing\reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
TypeError: cannot pickle 'weakref' object
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Program Files\Python3\lib\multiprocessing\spawn.py", line 116, in spawn_main
    exitcode = _main(fd, parent_sentinel)
  File "C:\Program Files\Python3\lib\multiprocessing\spawn.py", line 126, in _main
    self = reduction.pickle.load(from_parent)
EOFError: Ran out of input

标签: python-3.xlinuxwindowsmultiprocessing

解决方案


这不是操作系统相关的问题。问题是 Python 版本。我正在使用 Python 3.6.6 在 Windows 上运行您的代码,它工作正常,但对于 Python 3.9(适用于 Windows)失败。你也有 3.6 用于 Ubuntu,但 3.8 用于 Windows,因此表明这一点。

当您启动另一个流程并将先前启动的流程提供给该流程时,就会出现问题。这对于传递未启动的进程来说不是问题。在您的情况下,这是通过 self 完成的:在过程开始时self被腌制。

我在这里回答了同样的问题:https ://stackoverflow.com/a/65749012/13696660

简而言之,我认为最干净的解决方案是从酸洗对象中删除有问题的过程:

class A:
    def __init__(self):
        ...

    def __getstate__(self):
        # capture what is normally pickled
        state = self.__dict__.copy()

        # remove unpicklable/problematic variables
        # (multiprocessing.Process in this case)
        state['b'] = None
        state['d'] = None
        state['e'] = None
        state['g'] = None
        return state
...

现在它适用于我的 Windows 3.9。


推荐阅读