Press "Enter" to skip to content

Pyinstaller Run-time Information

你的应用在打包中运行和源码的运行时应该是完全相同的。但是,您可能希望在运行时了解应用是从源代码运行还是已打包(“冻结”)。您可以使用以下代码来检查“我们是否已打包?”:

import sys  
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):  
    print('运行在 PyInstaller 打包环境中')  
else:  
    print('运行在普通 Python 环境中')  

当打包应用程序启动时,引导程序会设置 sys.frozen 属性,并将打包文件夹的绝对路径存储在 sys._MEIPASS 中。对于单文件夹打包,这是指向打包文件夹内部 _internal 文件夹的路径;对于单文件打包,则是引导程序创建的临时文件夹的路径(详见单文件程序的工作原理)。

访问数据文件

运行中的应用可能需要访问以下位置的数据文件:

  1. 与应用一起打包的文件(详见添加数据文件)。
  2. 用户与应用程序包一起放置的文件,例如与应用程序位于同一文件夹。
  3. 用户当前工作目录中的文件。

程序可以通过多种变量访问这些文件。

使用 file

未打包时,Python 变量 file 表示模块所在的当前路径。当从打包脚本导入模块时,PyInstaller 引导程序会将模块的 file 属性设置为相对于打包文件夹的正确路径。

例如,如果从打包脚本中导入 mypackage.mymodule,则该模块的 file 属性将是 sys._MEIPASS + ‘mypackage/mymodule.pyc’。因此,如果您在打包时将一个数据文件 mypackage/file.dat 添加到 mypackage/file.dat,以下代码可以获取其路径:

from os import path  
path_to_dat = path.abspath(path.join(path.dirname(__file__), 'file.dat'))  

在主脚本(main 模块)中,file 变量包含脚本文件的路径。在 Python 3.8 及之前版本中,该路径可能是绝对路径或相对路径(取决于脚本如何传递给 Python 解释器);在 Python 3.9 及更高版本中,它始终是绝对路径。在打包脚本中,PyInstaller 引导程序总是将 main 模块中的 file 变量设置为打包目录内的绝对路径,就好像字节编译的入口点脚本就存在于该路径中。

例如,如果您的入口脚本名为 program.py,则打包脚本中的 file 属性将指向 sys._MEIPASS + ‘program.py’。因此,可以直接使用 sys._MEIPASS 或主脚本中 file 的父路径定位数据文件。

以下代码示例展示如何获取主脚本旁边的文件 other-file.dat 的路径(无论是否被打包):

from os import path  
bundle_dir = path.abspath(path.dirname(__file__))  
path_to_dat = path.join(bundle_dir, 'other-file.dat')  

或使用 pathlib:

from pathlib import Path  
path_to_dat = Path(__file__).resolve().with_name("other-file.dat")  

在打包内指定数据文件的位置

要将数据文件放置到代码期望的位置(例如相对于主脚本或打包目录),可以使用 –add-data=”source:dest” 命令行参数的 dest 参数。假设您通常在名为 my_script.py 的文件中使用以下代码定位文件 file.dat:

from os import path  
path_to_dat = path.abspath(path.join(path.dirname(__file__), 'file.dat'))  

对应的 PyInstaller 命令:

PyInstaller --add-data="/path/to/file.dat:."  

使用 sys.executable 和 sys.argv[0]

在普通 Python 脚本中,sys.executable 是被执行的程序的路径,即 Python 解释器的路径。而在打包应用中,sys.executable 也是被执行程序的路径,但此时指向引导程序或可执行文件路径。

sys.argv[0] 是用户命令中使用的名称或相对路径,可能是相对路径或绝对路径,具体取决于平台和启动方式。

恢复库路径

在运行系统程序时,需要还原原始路径以避免加载打包的库:

env = dict(os.environ)  # 复制环境变量  
lp_key = 'LD_LIBRARY_PATH'  # 对于 GNU/Linux 和 *BSD  
lp_orig = env.get(lp_key + '_ORIG')  
if lp_orig is not None:  
    env[lp_key] = lp_orig  

参考资料:

https://pyinstaller.org/en/stable/runtime-information.html

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注