我有一个使用scrapy的python脚本,我想使用pyinstaller将其转换为exe文件。生成的exe文件没有任何错误,但是当我打开它时会发生错误。
FileNotFoundError: [Errno 2] No such file or directory: '...\\scrapy\\VERSION'
我尝试过重新安装scrapy但是没有用。我正在使用带有python3的Windows 10
答案 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可以为您完成更多工作(防止您再获得ImportError
和FileNotFoundError
个)。见下文:
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 ,您将找到该文件。以下是您接下来要做的步骤: