我使用64位Python 3.3.0 CPython解释器在64位Linux(内核 版本2.6.28.4)计算机上运行自定义模拟器(用于生物学)。使用管道在进程之间传输Python对象时的字节限制?
因为模拟器依赖于许多独立实验的有效结果,我建立了并行处理运行实验。 之间的通信主要发生在生产者 - 消费者模式下,具有管理 multiprocessing Queue
s (doc)。 该架构的纲要如下:
- ,处理产卵和管理
Process
ES和产生模拟 - 1结果消费者过程中的各种
Queue
小号 - n个工作的处理的主流程,消耗模拟结果并对结果进行分类和分析
主进程和工作进程通过输入Queue
进行通信。 类似地,工作进程将其结果放置在输出Queue
中,结果消费者进程消耗来自其的项目。最终ResultConsumer 对象通过multiprocessing Pipe
(doc) 传递回主进程。
一切工作正常,直到它试图通过Pipe
传递ResultConsumer对象回 程师傅:
Traceback (most recent call last):
File "/home/cmccorma/.local/lib/python3.3/multiprocessing/process.py", line 258, in _bootstrap
self.run()
File "/home/cmccorma/.local/lib/python3.3/multiprocessing/process.py", line 95, in run
self._target(*self._args, **self._kwargs)
File "DomainArchitectureGenerator.py", line 93, in ResultsConsumerHandler
pipeConn.send(resCon)
File "/home/cmccorma/.local/lib/python3.3/multiprocessing/connection.py", line 207, in send
self._send_bytes(buf.getbuffer())
File "/home/cmccorma/.local/lib/python3.3/multiprocessing/connection.py", line 394, in _send_bytes
self._send(struct.pack("!i", n))
struct.error: 'i' format requires -2147483648 <= number <= 2147483647
我明白的前两个走线(在Process
库未处理退出), 和第三是我的代码行,用于将ResultConsumer对象向 Pipe
发送到主进程。最后两条痕迹是 有趣的地方。 A Pipe
泡菜发送给它的任何对象,并将 产生的字节传递到另一端(匹配连接),在运行recv()
时取消其中的 。 self._send_bytes(buf.getbuffer())
正在尝试 发送pickle对象的字节。 self._send(struct.pack("!i", n))
is 尝试打包长度为n的整数(网络/大端)的结构, 其中n是作为参数传入的缓冲区的长度(struct
库处理Python值与表示的C结构之间的转换as Python字符串,请参阅the doc)。
只有在尝试大量实验时才会出现此错误,例如, 10个实验 不会导致它,但1000会精心(所有其他参数是恒定的)。至于为什么struct.error
被抛出的原因,我最好的 假设是试图按下管道的字节数 超过2^32-1(2147483647)或〜2GB。
所以我的问题是双重的:
我卡住我的调查,因为
struct.py
基本上只是 从_struct
进口,我不知道在哪里是。字节限制似乎是任意的,因为底层架构全部是64位的 。那么,为什么我不能通过比这更大的东西呢?此外,如果我 无法更改此设置,是否有任何有益于此问题的解决方法?
注:我不认为在地方Pipe
的使用Queue
就能解决的问题,如 我怀疑Queue
的使用类似的酸洗中间步骤。 编辑:这个笔记完全不正确,正如在abarnert的答案中指出的那样。
如果你想要一个非常愚蠢的解决方法,你可以打开'process.py'并将该行更改为long或其他东西,但是这样你就必须在任何地方执行它,并且不知道它会破坏什么。 –
@SuperDisk:'process.py'中没有相关的行,并且没有int变为long(在Python 3.x中没有_is_ no'long'类型,甚至在2.7中它们是相同的类型) 。另外,要么monkeypatch'multiprocessing'好多了,要么分叉并保留一个单独的副本,然后修改stdlib。 – abarnert
@abarnert看起来像回溯线349。将'i'更改为'q'(这对结构模块来说很长)。也许我错了? –