【问题标题】:Python pickler.load() throwing FileNotFoundErrorPython pickle.load() 抛出 FileNotFoundError
【发布时间】:2020-12-05 17:16:57
【问题描述】:

我遇到了一个奇怪的问题,Python 会成功找到并读取存在的二进制文件,但 pickle.load() 不会。 pickle.load() 正在抛出一个没有多大意义的 FileNotFoundError。我知道该文件确实存在,因为如果我尝试读取文件的内容,我就可以。

try:
    with open("test", "rb") as f:
        print(f.read())
        data = pickle.load(f)

except FileNotFoundError as e:
    print(e)

几个小时以来,我一直在努力解决这个问题,但我就是不明白这里发生了什么。我有相当多的 Python 份额,但从未发生过这种情况。使用 VSCode 和 WSL (Ubuntu 20.04) 在 Windows 10 上工作。

编辑:我知道这个特定的代码不起作用,因为我首先使用 f.read() 阅读。我只是把它放在那里表明它有效,我只想pickle.load()它。

编辑:回溯是这样的:

Traceback (most recent call last):
  File "/mnt/d/_/Projects/FCUL/SO/pgrepwc/v2/hpgrepwc.py", line 34, in main
    data = pickle.load(f)
  File "/usr/lib/python3.8/multiprocessing/managers.py", line 959, in RebuildProxy
    return func(token, serializer, incref=incref, **kwds)
  File "/usr/lib/python3.8/multiprocessing/managers.py", line 809, in __init__
    self._incref()
  File "/usr/lib/python3.8/multiprocessing/managers.py", line 863, in _incref
    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

根据要求,我的目录列表:

prgrepwc:
    |
    |   histFile1
    |   histFile2
    |   .gitattributes
    |   .gitignore
    |   testFile
    |
    +---.vscode
    |       launch.json
    |       settings.json
    |
    |
    \---v2
        |
        |   testFile
        |   histFile
        |   hpgrepwc.py
        |   Load.py
        |   Match.py
        |   pgrepwc_v2.py
        \-- README.txt

我正在执行的文件是文件夹v2 中的hpgrepwc.py。我要读取的文件是二进制文件testFile。我注意到即使我的脚本在文件夹v2 中,有时它默认为pgrepwc,所以我什至在其中放置了testFile 的副本以防万一。无论如何都没有骰子,我也尝试将文件保存为.bin,但无济于事。

解决方案:

@tdelaney 提到:

"(...) 它看起来像是在 multiprocessing.Manager 中创建的某个对象 被腌制了。但这些对象实际上是广播的代理 对一组子流程的更改,并且在此之外无效 语境。在您的情况下, unpickler 试图重建一个类 试图重新连接到其早已死去的多处理合作伙伴。 您需要查看进行酸洗的代码并找出一些 其他封装数据的方式。”

就是这样。我在代码中大量使用multiprocessing.Manager 作为共享内存数据结构。在将 manager.dict() 转换为普通的 Python dict 之后,酸洗和解酸就像一个魅力。再次感谢所有做出贡献的人,尤其是@tdelaney。

【问题讨论】:

  • 此代码不起作用,因为您在尝试取消腌制之前已阅读到文件末尾。这应该导致 EOFError,而不是 FileNotFoundError。如果错误出现在open 调用上,那么问题只是当前工作目录中没有名为“test”的文件。我要求回溯,以便我们可以看到完整的错误消息和失败的行。
  • @NavaneethReddy - 这是不正确的。文件不需要扩展名。 Microsoft Windows 允许您通过文件扩展名将程序与文件相关联,并且不会执行代码,除非它具有 .exe 或其他明确定义的扩展名。类 Unix 系统不是这样工作的,并且通常不关心扩展名(如果有的话)是什么。在这种情况下,OP 打开文件并将文件句柄传递给pickle。 Pickle 只是读取那个文件,根本不在乎它来自哪里。
  • @zeval - 但读取有效吗?您可以将import traceback;traceback.print_exc() 添加到您的异常处理程序中以打印回溯,以便我们可以看到程序失败的位置。
  • @Zeval 您在代码中使用多处理/进程吗?这可能是相关的:stackoverflow.com/questions/56641428/…。该错误似乎与此问题中描述的错误有些相关
  • 通过该编辑,看起来在 multiprocessing.Manager 中创建的某些对象被腌制了。但这些对象实际上是向一组子进程广播更改的代理,并且在该上下文之外无效。在您的情况下,unpickler 试图重建一个试图重新连接到其长期死亡的多处理伙伴的类。您需要查看进行酸洗的代码并找出封装数据的其他方法。

标签: python file pickle


【解决方案1】:

确保您的类或对象中没有 multiprocessing.Manager 对象。我的对象中有一个 multiprocessing.Manager().dict() 。所以我用普通的 dict 替换了它,现在一切正常。

【讨论】:

    【解决方案2】:

    因此建议对扩展名为.pkl.pickle 的文件进行腌制。

    所以先用扩展名重新转储文件。

    with open('test.pickle', 'wb') as f:
        pickle.dump(your_contents, f)
    

    然后将loading 部分更改为:

    try:
        with open("test.pickle", "rb") as f:
            print(f.read())
            data = pickle.load(f)
    
    except FileNotFoundError as e:
        print(e)
    

    python 函数open 将读取带有扩展名的文件。只有当文件本身没有扩展名时,您才能排除扩展名。

    【讨论】:

    • 不,pickle 不在乎文件名是什么。它可能是ThisIsNotAPickleFile.TrustMe,读起来就很好。 pickle.load 实际上并没有打开文件,它只需要一个带有几个方法的对象。来自文档参数 *file* 必须有两个方法,一个采用整数参数的 read() 方法和一个不需要参数的 readline() 方法。。您可以使用拉入网页内容的阅读器、先解压缩的阅读器等... Pickle 不知道文件名,也不会以任何方式与文件名交互。
    • 抱歉,这对我不起作用。我试过.bin.pickle.pkl,但都没有工作,但又是 UNIX,所以这不是问题。
    • @tdelaney 这就是我在之前的评论部分告诉你的。 Pickle 不关心文件扩展名,但 .pickle 扩展名按照惯例使用。同样在 Windows 上,open 只会在指定扩展名的情况下读取文件。
    • @Zeval 如果您使用的是 unix,请尝试使用 cPickle 而不是 pickle。
    • @Zeval 我也不确定,但我看到 unix 用户使用cPickle 而不是pickle。我使用pickle,因为我是 Windows 用户。但我们是程序员,我们只是尝试一些东西,直到它趋于正常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2018-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-11
    相关资源
    最近更新 更多