【问题标题】:No such file or directory error using pyinstaller and scrapy使用pyinstaller和scrapy没有这样的文件或目录错误
【发布时间】:2022-05-05 05:06:52
【问题描述】:

我有一个使用scrapy 的python 脚本,我想使用pyinstaller 将它变成一个exe 文件。生成的exe文件没有任何错误,但是当我打开它时出现错误。

FileNotFoundError: [Errno 2] No such file or directory: '...\\scrapy\\VERSION'

我试过重新安装scrapy,但没有帮助。我正在使用带有 python3 的 Windows 10

【问题讨论】:

    标签: python scrapy pyinstaller


    【解决方案1】:

    完全披露:这是我对一个重复的类似问题的回答的重新发布。我只是把它放在这里是为了可见性。这真正回答了所提出的问题;所以它是相关的。

    您在构建独立程序时没有正确使用 Pyinstaller。以下是关于 Pyinstaller 工作原理的简短外行描述:Pyinstaller 捆绑了 Python 解释器、必要的 DLL(适用于 Windows)、项目的源代码以及 它可以找到的所有模块 放入文件夹或自解压可执行文件。 Pyinstaller 不包含在您运行 Pyinstaller 时生成的最终 .exe (Windows)、.app (macOS)、文件夹等中找不到的模块或文件。

    所以,这就是发生的事情:

     FileNotFoundError: [Errno 2] No such file or directory: '/tmp/_MEIbxALM3/scrapy/VERSION'
    

    您运行了冻结/独立程序。一旦你这样做了,你的程序就会被“解压”到你计算机上一个新的临时文件夹/temp/_MEIbxALM3/。此文件夹包含 Python 解释器、程序的源代码和 Pyinstaller 设法找到的模块(以及一些其他必要的文件)。

    Scrapy 模块不仅仅是一个模块。它是一个完整的框架。它有自己使用的纯文本文件(Python 文件除外)。而且,它本身会导入很多模块。

    Scrapy 框架尤其不能与 Pyinstaller 相处,因为它使用许多方法来导入 Pyinstaller 无法“看到”的模块。此外,Pyinstaller 基本上不会尝试在最终构建中包含不是 .py 文件的文件除非你告诉它

    那么,真正发生了什么?

    存在于您计算机上“普通”scrapy 模块中的文本文件“VERSION”(您已使用 pip 或 pipenv 安装)未包含在程序构建中的模仿 scrapy 模块中。 Scrapy 需要这个文件; Python 为您提供FileNotFoundError,因为它从未被包含在内。因此,您必须使用 Pyinstaller 将该文件包含在您的程序构建中。

    如何告诉 Pyinstaller 在哪里可以找到模块和文件?

    This guy 说只需将丢失的文件从计算机上安装它们的位置复制到从 Pyinstaller 吐出的构建文件夹中。这确实有效。但是,有一种更好的方法,Pyinstaller 可以为您做更多的工作(防止您可能得到进一步的ImportErrors 和FileNotFoundErrors)。见下文:

    build.spec 文件是你的朋友

    spec 文件只是 Python 文件,Pyinstaller 像配置文件一样使用它来告诉它如何构建程序。阅读更多关于他们的信息here。下面是一个真实的 build.spec 文件示例,我最近使用它来构建一个带有 Windows 图形用户界面的 Scrapy 程序(我的项目名称是 B.O.T. Bot):

    import gooey
    gooey_root = os.path.dirname(gooey.__file__)
    gooey_languages = Tree(os.path.join(gooey_root, 'languages'), prefix = 'gooey/languages')
    gooey_images = Tree(os.path.join(gooey_root, 'images'), prefix = 'gooey/images')
    a = Analysis(['botbotgui.py'],
                 pathex=['C:\\Users\\Colton\\.virtualenvs\\bot-bot-JBkeVQQB\\Scripts', 'C:\\Program Files (x86)\\Windows Kits\\10\\Redist\\ucrt\\DLLs\\x86'],
                 hiddenimports=['botbot.spiders.spider'],
                 hookspath=['.\\hooks\\'],
                 runtime_hooks=None,
                 datas=[('.\\spiders\\','.\\spiders\\'), ('.\\settings.py','.'),
                        ('.\\scrapy.cfg','.'), ('.\\items.py','.'), ('.\\itemloaders.py','.'),
                        ('.\\middlewares.py','.'), ('.\\pipelines.py','.')
                       ]
                 )
    pyz = PYZ(a.pure)
    
    options = [('u', None, 'OPTION'), ('u', None, 'OPTION'), ('u', None, 'OPTION')]
    
    exe = EXE(pyz,
              a.scripts,
              a.binaries,
              a.zipfiles,
              a.datas,
              options,
              gooey_languages, # Add them in to collected files
              gooey_images, # Same here.
              name='BOT_Bot_GUI',
              debug=False,
              strip=None,
              upx=True,
              console=False,
              windowed=True,
              icon=os.path.join(gooey_root, 'images', 'program_icon.ico'))
    
    #coll = COLLECT(exe,
        #a.binaries,
        #a.zipfiles,
        #a.datas,
        #options,
        #gooey_languages, # Add them in to collected files
        #gooey_images, # Same here.
        #name='BOT_Bot_GUI',
        #debug=False,
        #strip=False,
        #upx=True,
        #console=False,
        #windowed=True,
        #icon=os.path.join(gooey_root, 'images', 'program_icon.ico'))
    

    如果您想构建一个文件夹而不是独立的.exe,请取消注释最后一个区域。这是一个特定于我的计算机和项目结构的配置文件。因此,在您的文件中,您必须更改一些内容(例如,pathex 告诉 Pyinstaller 在 Windows 10 上哪里可以找到 DLL。但是,前提是相同的。

    我的项目目录如下所示:

    botbotgui.py  botbot.py  hooks  images  __init__.py  itemloaders.py  items.py  middlewares.py  pipelines.py  __pycache__  scrapy.cfg  settings.py  spiders
    

    特别注意hooks/ 目录。使用钩子可以让你免去很多麻烦。阅读更多关于 Pyinstaller 的钩子功能here。在hooks/ 目录中有一个用于 Scrapy 的挂钩文件。这将告诉 Pyinstaller 包含许多模块和文件如果你不使用 .spec 文件,它会错过这是迄今为止我在这里写的最重要的内容。如果您不执行此步骤,您将在每次尝试运行使用 Pyinstaller 构建的 Scrapy 程序时不断收到ImportErrors。 Scrapy 导入了 Pyinstaller 遗漏的许多模块。

    hook-scrapy.py(注意:你的钩子文件必须像这样命名。):

    from PyInstaller.utils.hooks import collect_submodules, collect_data_files
    
    # This collects all dynamically imported scrapy modules and data files.
    hiddenimports = (collect_submodules('scrapy') +
                     collect_submodules('scrapy.pipelines') +
                     collect_submodules('scrapy.extensions') +
                     collect_submodules('scrapy.utils')
    )
    datas = collect_data_files('scrapy')
    

    写完正确的build.spec 文件后,您需要做的就是在shell 提示符下像这样运行Pyinstaller:

    pyinstaller build.spec
    

    Pyinstaller 应该会生成一个可以正常工作的程序的正确版本。问题解决了。

    【讨论】:

    • 很好的解释@coltoneakins!我以前使用 pyinstaller 和 mne 信号分析包。在规范文件中,我必须添加一行datas=[background.png],它加载了所需的图像。当我尝试在命令行运行我的应用程序时,mne 开发人员添加了一个导致文件未找到错误的功能。我删除了上面的datas 并将其替换为datas=collect_data_files('mne') 并且一切正常!我不明白的是如何找到图像。可能是因为它位于我在 pathex 中列出的目录中吗?如何连接这两个数据?
    • @fishbacp - 要“连接两个数据”,您可以使用两种不同的方法:1) 只需执行 datas=[background.png],collect_data_files('mne') 或 2) 为 mne 创建自己的挂钩文件。与上面的hook-scrapy.py 类似,您将创建hook-mne.py,您可以在其中拥有:文件和规范文件中的“正常”data=[background.png]
    • 不错。 .png 之后的括号应该在那里还是紧跟在 'mne' 之后?
    • 我看到collect._data_files('mne') 是一长串有序对。我可以使用附加命令吗?可能类似于datas.append(something),其中“某物”是包含 background.png 的有序对?如果是这样,我不清楚订购的对是什么。
    • @fishbacp - 我实际上不确定我上面提到的 #1 方法的语法是否实际上是 data=[background.png],collect_data_files('mne')--我认为 pyinstaller 只需要一个列表。所以,是的,您可以将collect_data_files 返回的列表与您的 background.png 图像列表连接起来。
    【解决方案2】:

    您可以在 scrapy 包中找到该文件。转到此路径:Python/Lib/site-packages/scrapy,您将找到该文件。以下是您接下来要执行的步骤:

    1. 进入你的exe文件所在的目录,创建一个名为scrapy的文件夹。
    2. 从上面的路径中复制 VERSIONmime.types。 (如果你不复制 mime.types,只会出现另一个 no such file 错误。我只是在节省你的时间)
    3. 将这两个文件粘贴到您在步骤 1 中创建的 scrapy 文件夹中。
    4. 现在打开您的 exe 文件。如果出现No Module Error,则只需在要使用Pyinstaller的文件中导入相应的模块即可。

    祝你好运。 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-04
      • 1970-01-01
      • 1970-01-01
      • 2021-10-31
      • 1970-01-01
      相关资源
      最近更新 更多