可执行文件-确定pyIns生成的Python EXE中的应用程序路径
我有一个驻留在单个.py文件中的应用程序。 我已经能够让pyInstaller将其成功捆绑到Windows的EXE中。 问题是,应用程序需要一个.cfg文件,该文件始终直接位于同一目录中的应用程序旁边。
通常,我使用以下代码构建路径:
import os
config_name = 'myapp.cfg'
config_path = os.path.join(sys.path[0], config_name)
但是,当从pyInstaller生成的EXE调用sys.path时,它似乎为空。 当您运行python交互式命令行并尝试获取sys.path [0]时,也会发生相同的行为。
有没有更具体的方法来获取当前正在运行的应用程序的路径,以便我可以找到与其相关的文件?
6个解决方案
90 votes
我找到了解决方案。 您需要检查应用程序是作为脚本还是作为冻结的exe运行:
import os
import sys
config_name = 'myapp.cfg'
# determine if application is a script file or frozen exe
if getattr(sys, 'frozen', False):
application_path = os.path.dirname(sys.executable)
elif __file__:
application_path = os.path.dirname(__file__)
config_path = os.path.join(application_path, config_name)
Soviut answered 2020-02-10T01:21:25Z
24 votes
根据pyInstaller的文档,建议的恢复应用程序路径的方法如下:
#!/usr/bin/python3
import sys, os
if getattr(sys, 'frozen', False):
# If the application is run as a bundle, the pyInstaller bootloader
# extends the sys module by a flag frozen=True and sets the app
# path into variable _MEIPASS'.
application_path = sys._MEIPASS
else:
application_path = os.path.dirname(os.path.abspath(__file__))
已针对pyInstaller v3.2进行了测试,但这当然也适用于早期版本。
Soviut的解决方案不起作用,至少对于最新版本的pyInstaller而言通常不起作用(请注意,OP已经使用了很多年)。 例如,在MacOS上,将应用程序捆绑到一个文件捆绑中时,sys.executable仅指向嵌入式归档文件的位置,而不是在pyInstaller引导加载程序创建临时应用程序环境后该应用程序实际运行的位置。 只有sys._MEIPASS正确指向该位置。 有关pyInstaller的工作方式的更多信息,请参考此文档页面。
normanius answered 2020-02-10T01:21:55Z
6 votes
我把代码缩短了一点。
import os, sys
if getattr(sys, 'frozen', False):
application_path = os.path.dirname(sys.executable)
os.chdir(application_path)
logging.debug('CWD: ' + os.getcwd())
但是,sys._MEIPASS指向错误的目录。 我认为它也需要sys._MEIPASS + \app_name
Polv answered 2020-02-10T01:22:20Z
3 votes
os.path.dirname(sys.argv[0])
这对我行得通。
user1986021 answered 2020-02-10T01:22:39Z
1 votes
__file__从命令行使用python可执行文件工作。 在冻结模式下,它也提供没有实际路径的脚本文件名。 但是,它在交互模式下会产生错误。
以下内容适用于所有三种模式:
import sys,os
config_name = 'myapp.cfg'
if getattr(sys, 'frozen', False):
application_path = os.path.dirname(sys.executable)
running_mode = 'Frozen/executable'
else:
try:
app_full_path = os.path.realpath(__file__)
application_path = os.path.dirname(app_full_path)
running_mode = "Non-interactive (e.g. 'python myapp.py')"
except NameError:
application_path = os.getcwd()
running_mode = 'Interactive'
config_full_path = os.path.join(application_path, config_name)
print('Running mode:', running_mode)
print(' Appliction path :', application_path)
print(' Config full path :', config_full_path)
以三种不同模式输出:
Running mode: Interactive
Appliction path : C:\Projects\MyAppDir
Config full path : C:\Projects\MyAppDir\myapp.cfg
C:\Projects\MyAppDir>myapp.exe
Running mode: Frozen/executable
Appliction path : C:\Program Files\myapp
Config full path : C:\Program Files\myapp\myapp.cfg
C:\Projects\MyAppDir>python myapp.py
Running mode: Non-interactive (e.g. 'python myapp.py')
Appliction path : C:\Projects\MyAppDir
Config full path : C:\Projects\MyAppDir\myapp.cfg
C:\Projects\MyAppDir>
Rafiq answered 2020-02-10T01:23:08Z
0 votes
这里有很多答案,但我发现此解决方案在大多数情况下都适用:
import os
import sys
import os.path as op
try:
this_file = __file__
except NameError:
this_file = sys.argv[0]
this_file = op.abspath(this_file)
if getattr(sys, 'frozen', False):
application_path = getattr(sys, '_MEIPASS', op.dirname(sys.executable))
else:
application_path = op.dirname(this_file)
dashesy answered 2020-02-10T01:23:28Z