使用pyinstaller和scrapy没有这样的文件或目录错误

Dai*_*tas 1 python pyinstaller scrapy

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

FileNotFoundError: [Errno 2] No such file or directory: '...\\scrapy\\VERSION'
Run Code Online (Sandbox Code Playgroud)

我尝试重新安装scrapy,但这没有帮助。我正在将Windows 10与python3一起使用

col*_*ins 5

完全公开:这是我对重复的类似问题的回答的转贴。我只是为了可见而将其放在这里。这真正地回答了所提出的问题;因此很重要。

构建独立程序时,没有正确使用Pyinstaller。以下是对Pyinstaller的工作方式的简短介绍:Pyinstaller将Python解释器,必需的DLL(对于Windows),项目的源代码以及它可以找到的所有模块捆绑到文件夹或自解压的可执行文件中。Pyinstaller不包含在运行Pyinstaller时产生的最终.exe(Windows)、. app(macOS),文件夹等中找不到的模块或文件。

所以,这是发生了什么:

 FileNotFoundError: [Errno 2] No such file or directory: '/tmp/_MEIbxALM3/scrapy/VERSION'
Run Code Online (Sandbox Code Playgroud)

您运行了冻结/独立程序。完成此操作后,程序便被“提取”到计算机上的新临时文件夹中/temp/_MEIbxALM3/。该文件夹包含Python解释器,程序的源代码以及Pyinstaller设法找到的模块(以及其他一些必要的文件)。

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

Scrapy框架尤其不能与Pyinstaller配合使用,因为它使用许多方法来导入Pyinstaller无法“看到”的模块。另外,Pyinstaller基本上不会尝试在最终版本中包括不是.py文件的文件,除非您告知

那么,是什么真正发生了什么?

您计算机上的“普通”刮板模块中已存在的文本文件“版本”(已通过pip或pipenv安装)未包含在程序构建的copycat刮板模块中。Scrapy需要此文件。Python之所以给您,是FileNotFoundError因为它从未被包括在内。因此,您必须使用Pyinstaller将文件包含在程序的构建中。

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

这个家伙说,只需将丢失的文件从计算机上的安装位置复制到从Pyinstaller吐出的build文件夹中。这确实有效。但是,有一个更好的方法和Pyinstaller能为你做更多的工作(防止进一步的ImportErrorS和FileNotFoundError是你可以得到)。见下文:

build.spec 文件是您的朋友

spec文件只是Pyinstaller使用的Python文件(例如配置文件)来告诉它如何构建程序。在此处阅读有关它们的更多信息。下面是一个真实build.spec文件的示例,我最近用它为Windows的GUI构建Scrapy程序(我的项目名为BOT 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'))
Run Code Online (Sandbox Code Playgroud)

如果要构建文件夹而不是独立文件夹,请取消注释最后一个区域.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
Run Code Online (Sandbox Code Playgroud)

特别注意hooks/目录。使用钩子可以使您免于日后的头痛。在此处阅读有关Pyinstaller的钩子功能的更多信息。在hooks/目录中,有一个Scrapy的挂钩文件。这将告诉Pyinstaller包含许多模块和文件如果您不使用文件这些模块和文件将会丢失.spec到目前为止,这是我在这里写的最重要的内容。如果您不执行此步骤,则ImportError每次尝试运行使用Pyinstaller构建的Scrapy程序时,都会不断得到s。Scrapy导入了许多Pyinstaller错过的模块。

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

botbotgui.py  botbot.py  hooks  images  __init__.py  itemloaders.py  items.py  middlewares.py  pipelines.py  __pycache__  scrapy.cfg  settings.py  spiders
Run Code Online (Sandbox Code Playgroud)

After you finished writing a proper build.spec file, all you need to do is run Pyinstaller like this in your shell prompt:

pyinstaller build.spec
Run Code Online (Sandbox Code Playgroud)

Pyinstaller should then spit out a proper build of your program that should work. Problem solved.

Those Google'ing for an answer to this problem or really any issue with Pyinstaller or Scrapy, pray you find my answer.