【发布时间】:2019-09-19 23:23:15
【问题描述】:
我在由asyncio 生成的multiprocessing.Queue 中放置了一个ClientConnectionError 异常。我这样做是为了将 asyncio 中生成的异常传递回另一个线程/进程中的客户端。
我的假设是这个异常发生在反序列化过程中,从队列中读取异常。否则看起来几乎不可能到达。
Traceback (most recent call last):
File "model_neural_simplified.py", line 318, in <module>
main(**arg_parser())
File "model_neural_simplified.py", line 314, in main
globals()[command](**kwargs)
File "model_neural_simplified.py", line 304, in predict
next_neural_data, next_sample = reader.get_next_result()
File "/project_neural_mouse/src/asyncs3/s3reader.py", line 174, in get_next_result
result = future.result()
File "/usr/lib/python3.6/concurrent/futures/_base.py", line 432, in result
return self.__get_result()
File "/usr/lib/python3.6/concurrent/futures/_base.py", line 384, in __get_result
raise self._exception
File "/usr/lib/python3.6/concurrent/futures/thread.py", line 56, in run
result = self.fn(*self.args, **self.kwargs)
File "model_neural_simplified.py", line 245, in read_sample
f_bytes = s3f.read(read_size)
File "/project_neural_mouse/src/asyncs3/s3reader.py", line 374, in read
size, b = self._issue_request(S3Reader.READ, (self.url, size, self.position))
File "/project_neural_mouse/src/asyncs3/s3reader.py", line 389, in _issue_request
response = self.communication_channels[uuid].get()
File "/usr/lib/python3.6/multiprocessing/queues.py", line 113, in get
return _ForkingPickler.loads(res)
File "/usr/local/lib/python3.6/dist-packages/aiohttp/client_exceptions.py", line 133, in __init__
super().__init__(os_error.errno, os_error.strerror)
AttributeError: 'str' object has no attribute 'errno'
我想问这个问题有点远,但是有人知道这个问题吗?
Python 3.6.8,aiohttp.__version__ == 3.6.0
更新:
我设法重现了这个问题(感谢 cmets 中的 Samuel 改进了最小可重现测试用例,后来在 bugs.python.org 上的 xtreak 将其进一步提炼为仅用于 pickle 的测试用例):
import pickle
ose = OSError(1, 'unittest')
class SubOSError(OSError):
def __init__(self, foo, os_error):
super().__init__(os_error.errno, os_error.strerror)
cce = SubOSError(1, ose)
cce_pickled = pickle.dumps(cce)
pickle.loads(cce_pickled)
./python.exe ../backups/bpo38254.py
Traceback (most recent call last):
File "/Users/karthikeyansingaravelan/stuff/python/cpython/../backups/bpo38254.py", line 12, in <module>
pickle.loads(cce_pickled)
File "/Users/karthikeyansingaravelan/stuff/python/cpython/../backups/bpo38254.py", line 8, in __init__
super().__init__(os_error.errno, os_error.strerror)
AttributeError: 'str' object has no attribute 'errno'
参考资料:
【问题讨论】:
-
把bug报告贴错地方,移到aiohttp:github.com/aio-libs/aiohttp/issues/4077
-
您可以直接使用
pickle重现该问题:pickle.loads(pickle.dumps(aiohttp.client_exceptions.ClientConnectorError(connection_key, ose))) -
为了让您的示例更具代表性,我建议使用正确的
OSError初始化,例如OSError(1, "Reason string"),其中1是errno。 -
在调试时我发现了一些非常奇怪的东西:ClientConnectorError.__init__ 接收
errno(OSError的第一个参数)作为它自己的第一个参数,它被分配给connection_key!而os_error是原因字符串,而不是OSError实例本身。 -
这可能是由于
ClientConnectorError是OSError的子类和一些pickle怪癖(甚至是错误!?)
标签: python python-3.6 python-multiprocessing python-asyncio