python multiprocessing Process with Manager 表现异常

python multiprocessing Process with Manager behave strangly

所以我得到了两个非常相似的 python 文件 A 和 B,只有微小的区别:死循环语句的地方。第一个引发异常,而第二个按预期工作。但是为什么?!

代码A:

import json
import multiprocessing
from time import sleep

def aaa(shared_data):
    while True:
        sleep(1)
        shared_data["hello"] = "worldA"
        print(json.dumps(shared_data.copy()))


def bbb(shared_data):
    while True:
        sleep(1)
        shared_data["world"] = "helloB"
        print(json.dumps(shared_data.copy()))

def run():
    shared_data = multiprocessing.Manager().dict()
    multiprocessing.Process(target=aaa, args=(shared_data, )).start()
    multiprocessing.Process(target=bbb, args=(shared_data, )).start()

if __name__ == "__main__":
    run()
    while True:
        pass

代码 B:

import json
import multiprocessing
from time import sleep

def aaa(shared_data):
    while True:
        sleep(1)
        shared_data["hello"] = "worldA"
        print(json.dumps(shared_data.copy()))


def bbb(shared_data):
    while True:
        sleep(1)
        shared_data["world"] = "helloB"
        print(json.dumps(shared_data.copy()))

def run():
    shared_data = multiprocessing.Manager().dict()
    multiprocessing.Process(target=aaa, args=(shared_data, )).start()
    multiprocessing.Process(target=bbb, args=(shared_data, )).start()
    while True:
        pass

if __name__ == "__main__":
    run()

为什么第一个 引发异常 而第二个

第一个的输出,(除了异常之外什么都没有):

Process Process-3:
Traceback (most recent call last):
  File "/usr/lib/python3.8/multiprocessing/managers.py", line 827, in _callmethod
    conn = self._tls.connection
AttributeError: 'ForkAwareLocal' object has no attribute 'connection'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/usr/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "foo.py", line 21, in bbb
    shared_data["world"] = "hello" + str(cnt)
  File "<string>", line 2, in __setitem__
  File "/usr/lib/python3.8/multiprocessing/managers.py", line 831, in _callmethod
    self._connect()
  File "/usr/lib/python3.8/multiprocessing/managers.py", line 818, in _connect
    conn = self._Client(self._token.address, authkey=self._authkey)
Process Process-2:
  File "/usr/lib/python3.8/multiprocessing/connection.py", line 502, in Client
    c = SocketClient(address)
  File "/usr/lib/python3.8/multiprocessing/connection.py", line 630, in SocketClient
    s.connect(address)
FileNotFoundError: [Errno 2] No such file or directory
Traceback (most recent call last):
  File "/usr/lib/python3.8/multiprocessing/managers.py", line 827, in _callmethod
    conn = self._tls.connection
AttributeError: 'ForkAwareLocal' object has no attribute 'connection'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/usr/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "foo.py", line 12, in aaa
    shared_data["hello"] = "world" + str(cnt)
  File "<string>", line 2, in __setitem__
  File "/usr/lib/python3.8/multiprocessing/managers.py", line 831, in _callmethod
    self._connect()
  File "/usr/lib/python3.8/multiprocessing/managers.py", line 818, in _connect
    conn = self._Client(self._token.address, authkey=self._authkey)
  File "/usr/lib/python3.8/multiprocessing/connection.py", line 502, in Client
    c = SocketClient(address)
  File "/usr/lib/python3.8/multiprocessing/connection.py", line 630, in SocketClient
    s.connect(address)
FileNotFoundError: [Errno 2] No such file or directory

第二个输出(如预期):

{"hello": "worldA"}
{"hello": "worldA", "world": "helloB"}
{"hello": "worldA", "world": "helloB"}
{"hello": "worldA", "world": "helloB"}
{"hello": "worldA", "world": "helloB"}
{"hello": "worldA", "world": "helloB"}
{"hello": "worldA", "world": "helloB"}
{"hello": "worldA", "world": "helloB"}
...

我正在使用 Python 3.8.5 和 'Ubuntu 20.04.1 LTS (Focal Fossa)'。

已解决,原因是shared_datarun后被销毁,改成这样可以:

def run():
    shared_data = multiprocessing.Manager().dict()
    multiprocessing.Process(target=aaa, args=(shared_data, )).start()
    multiprocessing.Process(target=bbb, args=(shared_data, )).start()
    return shared_data

if __name__ == "__main__":
    _ = run()
    while True:
        pass