如何在py2exe中获取可执行文件的当前目录?
我在我的脚本中使用了一段代码,目的是跨平台地确定脚本的运行位置:
SCRIPT_ROOT = os.path.dirname(os.path.realpath(__file__))
这段代码很简单。接下来,我会在脚本的其他地方使用 SCRIPT_ROOT
,以确保所有路径都是相对的。我的问题出现在我通过 py2exe 运行它的时候,因为生成的可执行文件没有设置 __file__
,所以我的脚本就出错了。有没有人知道怎么解决或者绕过这个问题?
4 个回答
试试这个:
import os
import sys
os.path.realpath(os.path.dirname(sys.argv[0]))
Py2exe并没有定义__file__
这个东西:http://www.py2exe.org/index.cgi/Py2exeEnvironment
提问者想要一个适合py2exe的版本:
SCRIPT_ROOT = os.path.dirname(os.path.realpath(__file__))
最好的办法是判断Python程序是否被打包成了exe文件,py2exe有相关的文档说明这个问题:http://www.py2exe.org/index.cgi/HowToDetermineIfRunningFromExe
import imp, os, sys
def main_is_frozen():
return (hasattr(sys, "frozen") or # new py2exe
hasattr(sys, "importers") # old py2exe
or imp.is_frozen("__main__")) # tools/freeze
def get_main_dir():
if main_is_frozen():
return os.path.dirname(sys.executable)
return os.path.dirname(os.path.realpath(__file__))
SCRIPT_ROOT = get_main_dir()
因为Python是EAFP的,所以这里有一个EAFP版本...
try:
if sys.frozen or sys.importers:
SCRIPT_ROOT = os.path.dirname(sys.executable)
except AttributeError:
SCRIPT_ROOT = os.path.dirname(os.path.realpath(__file__))
谢谢!
这里是py2exe的文档参考,以下是一些相关内容:
sys.executable
是指exe文件的完整路径。sys.argv
的第一个项目是可执行文件的完整路径,后面的都是命令行参数。sys.frozen
只在可执行文件中存在。对于控制台可执行文件,它的值是“console_exe”;对于没有控制台的图形界面可执行文件,它的值是“windows_exe”;对于进程内的dll服务器,它的值是“dll”。__file__
是没有定义的(你可能想用sys.argv[0]
来代替)。
从这些文档中并不清楚“exe文件”和“可执行文件”是否是同一个东西,因此也不确定 sys.executable
和 sys.argv[0]
是否是一样的。根据我之前处理过的代码,它同时适用于 script.py 和 py2exe_executable.exe,我发现了类似这样的内容:
if hasattr(sys, 'frozen'):
basis = sys.executable
else:
basis = sys.argv[0]
required_folder = os.path.split(basis)[0]
如我所说,这段代码是有效的,但我不记得当时为什么觉得这样做是必要的,而不是直接使用 sys.argv[0]
。
仅使用 basis
就足够完成当前的任务(读取该目录下的文件)。为了更永久的记录,可以分开处理像 os.path.realpath(basis)
这样的内容。
更新 实际上做了一个测试;这比猜测和空谈要好得多 :-)
总结:忽略 sys.frozen,忽略 sys.executable,毫无条件使用 sys.argv[0]。
证据:
=== foo.py ===
# coding: ascii
import sys, os.path
print 'sys has frozen:', hasattr(sys, 'frozen')
print 'using sys.executable:', repr(os.path.dirname(os.path.realpath(sys.executable)))
print 'using sys.argv[0]:', repr(os.path.dirname(os.path.realpath(sys.argv[0] )))
=== setup.py ===
from distutils.core import setup
import py2exe
setup(console=['foo.py'])
=== 结果 ===
C:\junk\so\py2exe>\python26\python foo.py
sys has frozen: False
using sys.executable: 'C:\\python26'
using sys.argv[0]: 'C:\\junk\\so\\py2exe' # where foo.py lives
C:\junk\so\py2exe>dist\foo
sys has frozen: True
using sys.executable: 'C:\\junk\\so\\py2exe\\dist'
using sys.argv[0]: 'C:\\junk\\so\\py2exe\\dist' # where foo.exe lives