pyinstaller似乎找不到数据文件

7 投票
3 回答
9110 浏览
提问于 2025-04-17 04:42

编辑3:我把 __file__ 替换成了 sys.argv[0],这样我就能知道我的脚本或可执行文件的位置。虽然这两者不完全一样,但在我的情况下运行得很好(至少在可执行版本上是这样)。现在一切都正常了,使用了一种被接受的答案中的方法来访问资源文件,所有功能都在单文件模式下正常工作!


编辑2:正如被接受的答案中的评论所示,问题出在我的脚本路径解析上;我试图使用 __file__ 来获取脚本的位置,以便访问它的资源文件。但一旦打包后,这个方法就不管用了,因为 __file__ 会返回来自 Python.dll 的文件名,这样几乎总是没有路径,只有文件名。因此,我必须找到其他方法来访问资源文件;目前的一个变通办法是把当前目录移动到可执行文件的路径。

顺便说一下,这意味着 ConfigParser 在访问文件时应该报告问题,而不是说某个部分缺失。

我会更新这个问题,告诉大家我是如何解决这个路径解析问题的。


我在使用 pyinstaller 时遇到了问题,因为这是我第一次使用它,肯定是我做错了什么。

所以,问题是这样的:pyinstaller 在我写的脚本上运行得很顺利,并在 dist 文件夹中生成了一些东西。好的,现在我想执行它,看看一切是否正常,但我得到了以下结果:

C:\Program Files\PyInstaller\pyinstaller-1.5.1>p_tool\dist\p_tool\p_tool.exe -?
Traceback (most recent call last):
  File "<string>", line 104, in <module>
  File "p_tool\build\pyi.win32\p_tool\outPYZ1.pyz/logging.config", line 76, in f
ileConfig
  File "p_tool\build\pyi.win32\p_tool\outPYZ1.pyz/logging.config", line 112, in
_create_formatters
  File "p_tool\build\pyi.win32\p_tool\outPYZ1.pyz/ConfigParser", line 532, in ge
t
ConfigParser.NoSectionError: No section: 'formatters'

我最初的想法是 logging.conf 文件缺失,所以我在 p_tool.spec 文件中添加了它(还有一些其他资源文件),但情况并没有好转。

Python 版本:2.6.6,运行在 WinXP 上。我使用 pyinstaller 是因为我需要将文件打包到 Solaris 工作站。

那么,有人遇到过这个问题吗?唯一相关的话题是以下问题:PyInstaller 问题,与我的问题非常接近,但可惜的是没有得到答案。


编辑3:与日志相关的细节已删除,因为与问题并不太相关。

3 个回答

0

这个错误信息 ConfigParser.NoSectionError: No section: 'formatters' 的意思是,问题不是文件丢失了,而是文件里缺少了一个叫做 'formatters' 的部分。

0

我遇到过类似的问题,但到现在为止还没找到一个优雅的解决办法。我用的“窍门”是这样的:假设我的项目放在 '~/project/project_root' 这个位置,首先在 .spec 文件中:

excluded_sources = TOC([x for x in a.pure if not x[0].startswith('project_root')])

这里的 a 是一个 Analysis 对象,基本上我把我项目里的所有文件从 PYZ 中移除了,这样就不会有任何导入从这里传递过去,日志的相对路径也不会从这里计算。之后,我从项目中创建一个 Tree 对象。

my_project_tree = Tree('~/project')

然后把这个 Tree 加入到传递给 COLLECT 的 TOC 列表中,所以:

COLLECT( exe,
           a.binaries,
           a.zipfiles,
           a.datas,
           my_project_tree,
           ....)

这样你就应该能把你的项目文件夹添加到 dist 文件夹里。问题是,这样你也会把项目的 pyc 文件一起分发出去,但到现在为止我还没找到更好的办法。我对有效的解决方案非常感兴趣。

10

首先,在读取配置文件之前,最好先打印一下配置文件的路径和它是否存在,这样你就能确认文件在哪里,Python能否找到它。

至于如何实际访问这个文件,os.path.split(__file__) 看起来差不多是对的,但我不确定在使用 pyinstaller 时它是否能正常工作。正确的打包文件的方法是把它们添加到 .spec 文件中,pyinstaller 会在编译时加载这些文件,并在运行时把它们解压到 $_MEIPASS2/ 目录下。为了在打包模式下获取 _MEIPASS2 目录,并在解压(开发)模式下使用本地目录,我使用了以下代码:

def resource_path(relative):
    return os.path.join(
        os.environ.get(
            "_MEIPASS2",
            os.path.abspath(".")
        ),
        relative
    )


# in development
>>> resource_path("logging.conf")
"/home/shish/src/my_app/logging.conf"

# in deployment
>>> resource_path("logging.conf")
"/tmp/_MEI34121/logging.conf"

撰写回答