Python Pickle 抛出 FileNotFoundError。

4

我在Python中遇到了一个问题,在一个与其他进程一起运行的可运行对象中,发生了以下情况:如果代码仅仅是:

f = open(filename, "rb")
f.close()

没有错误,但是当代码更改为以下内容,并在中间引入pickle时,它会抛出FileNotFoundError

f = open(filename, "rb")
object = pickle.load(f)
f.close()

我不明白为什么,如果文件已经存在,pickle还会抛出这样的错误。完整的错误跟踪如下:

task = pickle.load(f)
File "/usr/lib/python3.4/multiprocessing/managers.py", line 852, in RebuildProxy
   return func(token, serializer, incref=incref, **kwds)
File "/usr/lib/python3.4/multiprocessing/managers.py", line 706, in __init__
   self._incref()
File "/usr/lib/python3.4/multiprocessing/managers.py", line 756, in _incref
   conn = self._Client(self._token.address, authkey=self._authkey)
File "/usr/lib/python3.4/multiprocessing/connection.py", line 495, in Client
   c = SocketClient(address)
File "/usr/lib/python3.4/multiprocessing/connection.py", line 624, in SocketClient
   s.connect(address)
FileNotFoundError: [Errno 2] No such file or directory

2
请问您能否贴出完整的错误信息? - TessellatingHeckler
1
这显然不是一个可以通过你提供的信息来重现或验证错误。甚至无法进行除了说“那不应该发生;要么你误解了发生了什么,要么你的 pickle 或者 stdlib 出了点问题”之外的调试工作,这对你并没有帮助。请参考 MCVE (http://stackoverflow.com/help/mcve)以获取在问题中包含哪些内容的指导。 - abarnert
1
@JadieldeArmas:不, 请发布完整的回溯信息,而不仅仅是错误字符串。此外,请将其编辑到问题中,而不是在评论中发布。 - abarnert
是的,文件名存在。文件名的内容是用户定义类对象的列表。 - Jadiel de Armas
3
看起来与 pickle 内容有关,而不是包含 pickle 的文件。也许可以参考这篇文章 http://jodal.no/post/3669476502/pickling-multiprocessing-connection-objects/ - 可以将 Multiprocessing 连接进行序列化,但无法反序列化。或者说,反序列化会触发到不可用的端点的套接字连接。 - TessellatingHeckler
显示剩余6条评论
1个回答

2

虽然我认为@TesselatingHeckler提供了答案,但这个评论并不适合放在评论区...所以它是那个答案的扩展。

您无法对multiprocessing QueuePipe对象进行pickle,实际上,一些pickled对象仅在load时失败。

我已经构建了一个multiprocessing分支,允许大多数对象被pickle。主要做的事情是用一个更强大的序列化程序(dill)替换pickle。该分支作为pathos包的一部分(在github上)可用。我以前尝试过序列化Pipes,它可以工作,它也可以在python的socket和python的Queue上工作。然而,显然它仍然不能在 Queue上工作。

>>> from processing import Pipe
>>> p = Pipe()
>>> 
>>> import dill
>>> dill.loads(dill.dumps(p))
(Connection(handle=12), Connection(handle=14))
>>>
>>> from socket import socket
>>> s = socket()
>>> from Queue import Queue as que
>>> w = que()
>>> dill.loads(dill.dumps(s))
<socket._socketobject object at 0x10dae18a0>
>>> dill.loads(dill.dumps(w))
<Queue.Queue instance at 0x10db49f38>
>>>
>>> from processing import Queue
>>> q = Queue()
>>> dill.loads(dill.dumps(q))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mmckerns/lib/python2.7/site-packages/dill-0.2.2.dev-py2.7.egg/dill/dill.py", line 180, in dumps
    dump(obj, file, protocol, byref, file_mode, safeio)
  File "/Users/mmckerns/lib/python2.7/site-packages/dill-0.2.2.dev-py2.7.egg/dill/dill.py", line 173, in dump
    pik.dump(obj)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump
    self.save(obj)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 306, in save
    rv = reduce(self.proto)
  File "/Users/mmckerns/lib/python2.7/site-packages/processing/queue.py", line 62, in __getstate__
    assertSpawning(self)
  File "/Users/mmckerns/lib/python2.7/site-packages/processing/forking.py", line 24, in assertSpawning
    'processes through inheritance' % type(self).__name__)
RuntimeError: Queue objects should only be shared between processes through inheritance

看起来,对于multiprocessingQueue__getstate__方法被硬编码为会抛出一个错误。如果你将其嵌入到一个类中,可能直到类实例从pickle中重新构建时才触发。

尝试使用picklemultiprocessingQueue进行pickle也会导致上述错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接