【问题标题】:how can i get the executable's current directory in py2exe?如何在 py2exe 中获取可执行文件的当前目录?
【发布时间】:2011-01-18 13:26:33
【问题描述】:

我在我的脚本中使用这段代码以跨平台的方式精确定位它的运行位置:

SCRIPT_ROOT = os.path.dirname(os.path.realpath(__file__))

很简单。然后我继续在脚本的其他区域使用SCRIPT_ROOT 以确保一切都是正确的。当我通过py2exe运行它时会出现我的问题,因为生成的可执行文件没有设置__file__,因此我的脚本会中断。有谁知道如何解决或解决这个问题?

【问题讨论】:

标签: python py2exe


【解决方案1】:

这里是py2exe documentation reference,这里是相关项目:

  • sys.executable 设置为 exe 文件的完整路径名。
  • sys.argv 中的第一项是可执行文件的完整路径名,其余是命令行参数。
  • sys.frozen 只存在于可执行文件中。对于控制台可执行文件,它设置为“console_exe”,对于无控制台的 gui 可执行文件,设置为“windows_exe”,对于进程内 dll 服务器,设置为“dll”。
  • __file__ 未定义(您可能想改用 sys.argv[0])

从这些文档中看不出“exe 文件”和“可执行文件”是否相同,因此 sys.executablesys.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

【讨论】:

  • 我相信sys.executable通常指向python解释器本身,这是你在py2exe下想要的,但不是。
  • @prestomation:py2exe 案例中的“Python 解释器本身”是什么? “但不是其他”是什么意思?
  • "otherwise" 是在您运行解释文件时,这是大多数环境。在 py2exe 的情况下,我想解释器是你的 py2exe,因为它包含在内。您最近的编辑似乎证实了这一点。
  • 如果将可执行文件放入搜索路径(PATH 环境变量)上的目录会发生什么?我发现sys.argv[0]在这种情况下没有目录组件。
  • @Ber 是的,我认为 sys.argv[0] 将捕获当前工作目录,可能不是您想要的...
【解决方案2】:

Py2exe 没有定义__file__:http://www.py2exe.org/index.cgi/Py2exeEnvironment

OP 请求 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__))

干杯!

【讨论】:

  • @Ber 你是对的......我应该更仔细地阅读。更好?
  • 这正是问题所要求的。感谢您的出色解决方案。
  • 这是一个比公认的更好的答案
【解决方案3】:

试试这个:

import os
import sys
os.path.realpath(os.path.dirname(sys.argv[0]))

【讨论】:

  • 根据我的经验,当通过 PATH 变量找到程序时,使用 sys.argv [0] 没有指向它的路径。
  • @Ber, ...但是,py2exe 是一种特殊情况,并且在所有情况下都将其设置为完全限定值。
【解决方案4】:

sys.argv[0] 是获取路径的可靠方法,因为无论作为脚本或 exe 运行,它都会给出相同的结果 .获取目录os.path.dirname(sys.argv[0])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-20
    • 2020-11-15
    • 2018-03-26
    • 2011-02-19
    • 2013-09-03
    • 1970-01-01
    • 2012-01-10
    • 1970-01-01
    相关资源
    最近更新 更多