scrapy 上的 Pyinstaller 错误?
Pyinstaller error on scrapy?
我正在使用 scrapy 导入它。我使用 pyinstaller 构建了 python 文件。构建后我 运行 文件 ./new.py。但是错误弹出:
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/_MEIbxALM3/scrapy/VERSION'
[23450] Failed to execute script new
您在构建独立程序时没有正确使用 Pyinstaller。这是 Pyinstaller 工作原理的简短外行描述:Pyinstaller 捆绑了 Python 解释器、必要的 DLL(对于 Windows)、项目的源代码和 所有它可以找到 的模块到文件夹或自解压可执行文件中。 Pyinstaller 不包含它在最终的 .exe (Windows)、.app (macOS)、文件夹等中找不到的模块或文件,当您 运行 Pyinstaller.
所以,事情是这样的:
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/_MEIbxALM3/scrapy/VERSION'
你 运行 你的 frozen/stand-alone 程序。一旦你这样做了,你的程序就会 'extracted' 到你计算机上的一个新的临时文件夹 /temp/_MEIbxALM3/
。此文件夹包含 Python 解释器、程序的源代码和 Pyinstaller 设法找到的模块(加上其他几个必要的文件)。
Scrapy 模块不仅仅是一个模块。它是一个完整的框架。它有自己使用的纯文本文件(除了 Python 文件)。而且,它自己导入了很多模块。
Scrapy 框架尤其不能与 Pyinstaller 相处,因为它使用许多方法来导入 Pyinstaller 无法导入的模块 'see'。此外,Pyinstaller 基本上不会尝试在最终构建中包含非 .py 文件的文件 ,除非你告诉它 。
那么,真的发生了什么?
您计算机上的 'normal' scrapy 模块中存在的文本文件 'VERSION'(您使用 pip 或 pipenv 安装的)未包含在您构建的 copycat scrapy 模块中程序。 Scrapy 需要这个文件; Python 给你的是 FileNotFoundError
,因为它从未被包括在内。因此,您必须在使用 Pyinstaller 构建程序时包含该文件。
你如何告诉 Pyinstaller 在哪里可以找到模块和文件?
This guy 说只需将丢失的文件从它们在计算机上的安装位置复制到从 Pyinstaller 吐出的构建文件夹中。这确实有效。但是,有一种更好的方法,Pyinstaller 可以为您做更多的工作(防止您可能得到进一步的 ImportError
s 和 FileNotFoundError
s)。见下文:
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 的钩子文件。这将告诉 Pyinstaller 包含许多模块和文件 如果您不使用 .spec
文件,否则它会错过 。 这是迄今为止我在这里写的最重要的东西。 如果你不做这一步,你每次尝试 [=106= 时都会得到 ImportError
s ] 使用 Pyinstaller 构建的 Scrapy 程序。 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
文件后,你需要做的就是 运行 Pyinstaller 在你的 shell 提示符下这样:
pyinstaller build.spec
Pyinstaller 然后应该吐出一个应该工作的程序的正确构建。问题已解决。
我正在使用 scrapy 导入它。我使用 pyinstaller 构建了 python 文件。构建后我 运行 文件 ./new.py。但是错误弹出:
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/_MEIbxALM3/scrapy/VERSION'
[23450] Failed to execute script new
您在构建独立程序时没有正确使用 Pyinstaller。这是 Pyinstaller 工作原理的简短外行描述:Pyinstaller 捆绑了 Python 解释器、必要的 DLL(对于 Windows)、项目的源代码和 所有它可以找到 的模块到文件夹或自解压可执行文件中。 Pyinstaller 不包含它在最终的 .exe (Windows)、.app (macOS)、文件夹等中找不到的模块或文件,当您 运行 Pyinstaller.
所以,事情是这样的:
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/_MEIbxALM3/scrapy/VERSION'
你 运行 你的 frozen/stand-alone 程序。一旦你这样做了,你的程序就会 'extracted' 到你计算机上的一个新的临时文件夹 /temp/_MEIbxALM3/
。此文件夹包含 Python 解释器、程序的源代码和 Pyinstaller 设法找到的模块(加上其他几个必要的文件)。
Scrapy 模块不仅仅是一个模块。它是一个完整的框架。它有自己使用的纯文本文件(除了 Python 文件)。而且,它自己导入了很多模块。
Scrapy 框架尤其不能与 Pyinstaller 相处,因为它使用许多方法来导入 Pyinstaller 无法导入的模块 'see'。此外,Pyinstaller 基本上不会尝试在最终构建中包含非 .py 文件的文件 ,除非你告诉它 。
那么,真的发生了什么?
您计算机上的 'normal' scrapy 模块中存在的文本文件 'VERSION'(您使用 pip 或 pipenv 安装的)未包含在您构建的 copycat scrapy 模块中程序。 Scrapy 需要这个文件; Python 给你的是 FileNotFoundError
,因为它从未被包括在内。因此,您必须在使用 Pyinstaller 构建程序时包含该文件。
你如何告诉 Pyinstaller 在哪里可以找到模块和文件?
This guy 说只需将丢失的文件从它们在计算机上的安装位置复制到从 Pyinstaller 吐出的构建文件夹中。这确实有效。但是,有一种更好的方法,Pyinstaller 可以为您做更多的工作(防止您可能得到进一步的 ImportError
s 和 FileNotFoundError
s)。见下文:
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 的钩子文件。这将告诉 Pyinstaller 包含许多模块和文件 如果您不使用 .spec
文件,否则它会错过 。 这是迄今为止我在这里写的最重要的东西。 如果你不做这一步,你每次尝试 [=106= 时都会得到 ImportError
s ] 使用 Pyinstaller 构建的 Scrapy 程序。 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
文件后,你需要做的就是 运行 Pyinstaller 在你的 shell 提示符下这样:
pyinstaller build.spec
Pyinstaller 然后应该吐出一个应该工作的程序的正确构建。问题已解决。