如何让 pyinstaller 查看基于主目录的配置文件?

Posted

技术标签:

【中文标题】如何让 pyinstaller 查看基于主目录的配置文件?【英文标题】:How can I make pyinstaller look at a home dir based config file? 【发布时间】:2020-03-09 14:23:59 【问题描述】:

TLDR

为了让我的问题更清楚一点,我不想将配置文件与 pyinstaller 捆绑在一起。这是因为如果它不存在,应用程序将创建它。我想要做的是让 pyinstaller 编译二进制文件来读取配置文件(如果它已经存在)。

我正在尝试在一个小项目上使用 pyinstaller,该项目使用基于 configparser 的 ini 文件来加载某些变量。当我的项目使用 pip 安装并首次运行时,它将查找并且如果不存在,则在主目录中创建必要的配置文件。这适用于 windows、osx 和 linux。

我遇到的问题是,当我使用 pyinstaller 编译项目时,它不会寻找这个。

我的问题是,我如何编译我的项目,以便它在运行时查看配置文件的指定位置?最好使用onefile 选项。我的项目是here。

例如,在我的配置文件中,我有一个名为 pluginpath 的配置对象。如果我运行我的 pip 安装项目,则从基于家庭的配置文件中读取插件路径,并打印路径(如果我向其添加了新值)。但是如果我从编译的二进制文件中运行它,那么它会打印None,这是默认值。

我的规范生成了一个文件规范文件

# -*- mode: python ; coding: utf-8 -*-

block_cipher = None


a = Analysis(['cli.py'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='chepy',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=None,
          console=True )

【问题讨论】:

【参考方案1】:

更新答案

我想改变你原来的代码

home = Path.home()
self.chepy_dir = (
    Path(".chepy").resolve()
    if Path(".chepy").exists()
    else Path(home / ".chepy")
)
self.chepy_conf = Path(self.chepy_dir / "chepy.conf")

这会起作用

home = Path.home()
self.chepy_dir = (
    Path(home / ".chepy").resolve()
    if Path(home / ".chepy").exists()
    else Path(home / ".chepy")
)
self.chepy_conf = Path(self.chepy_dir / "chepy.conf")

home 在两个Path 中,它将在用户主目录中查找.chepy,而不是chepy/chepy/config.py 所在的文件夹,即chepy/chepy

原答案

我认为您正在谈论在运行时读取配置文件。相关的pyinstaller 文档在这里。 run-time-information

您不需要更改spec 文件,但您需要注意运行时要读取的文件路径执行捆绑应用程序的路径

例如,你有一个example.py:

with open('a.txt') as f:
        print(f.read())

编译后,它会读取执行命令的文件夹中的a.txt

pyinstaller example.py之后的文件结构如下:

--
 - example.py
 - dist/
   - example/
     - ...
     - example.exe

如果您在当前目录中运行.\dist\example\example.exe,捆绑的应用程序将在当前目录中查找a.txt

如果您在dist 文件夹中运行.\example\example.exe,捆绑的应用程序将在dist 文件夹中查找a.txt

【讨论】:

谢谢!但这不完全是我的问题。读取配置文件的方式是从pathlib.Path 解析绝对配置文件路径。所以我的问题是编译的应用程序并没有真正阅读该上下文。你可以看到here 配置文件是如何被读取的。 谢谢!实际上,我以这种方式编写代码是有原因的。如果用户想要使用运行应用程序的 PWD 中的临时 conf 文件,则 Path(".chepy").resolve() 会处理该问题。这就是为什么设置Path(home / ".chepy").resolve() 会破坏该功能,因为它只能在主目录文件夹上工作。应用程序的行为是,如果 pwd 中有 conf 文件,则使用 conf 文件。否则检查主目录中的 conf 文件,如果存在则使用它,如果不存在则创建一个。因为有了路径,我可以得到 CWD 上下文。

以上是关于如何让 pyinstaller 查看基于主目录的配置文件?的主要内容,如果未能解决你的问题,请参考以下文章

基于py打包了一个exe文件,里面涉及的数据位于MySQL中,怎么让其他人也能正常使用exe?

如何使用pyinstaller打包python文件为exe文件

如何在win7 64位系统下用pyinstaller打包python代码成exe

如何在win7 64位系统下用pyinstaller打包python代码成exe

Python | pyinstaller 打包exe

如何始终在其所在目录执行 PyInstaller / Platypus 编译的 Python 可执行文件