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

时间:2018-03-03 15:45:53

标签: python scrapy pyinstaller

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

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

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

2 个答案:

答案 0 :(得分:3)

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

构建独立程序时,没有正确使用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文件的文件,除非您告诉它。

那么,确实发生了什么事?

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

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

This guy说,只需将丢失的文件从计算机上的安装位置复制到从Pyinstaller吐出的build文件夹中。这确实有效。但是,有一种更好的方法,Pyinstaller可以为您完成更多工作(防止您再获得ImportErrorFileNotFoundError个)。见下文:

build.spec文件是您的朋友

spec文件只是Pyinstaller使用的Python文件(例如配置文件)来告诉它如何构建程序。详细了解它们here。下面是一个真实的build.spec文件的示例,我最近用它来构建带有Windows的GUI的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的挂钩文件。如果您不使用.spec文件,这将告诉Pyinstaller包含许多模块和文件,否则会丢失。 这是到目前为止我在这里写的最重要的内容。如果不执行此步骤,每次尝试运行使用Pyinstaller构建的Scrapy程序时,都会得到ImportError 。 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应该吐出正确的程序版本,该程序应该可以运行。问题解决了。

那些Google希望为该问题或Pyinstaller或Scrapy的任何问题提供答案的人,请祈祷能找到我的答案。

答案 1 :(得分:1)

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

  1. 转到exe文件所在的目录,然后创建名为scrapy的文件夹。
  2. 从上面的路径中复制 VERSION mime.types 。 (如果你不复制 mime.types ,就会有另一个没有这样的文件错误。我只是在节省你的时间)
  3. 将这两个文件粘贴到您在步骤1中创建的scrapy文件夹中。
  4. 现在打开你的exe文件。如果出现无模块错误,则只需要导入要使用Pyinstaller的文件中的相应模块。
  5. 祝你好运。 :)