20

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

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

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

4

4 回答 4

25

Here is the py2exe documentation reference and here are the relevant items:

  • sys.executable is set to the full pathname of the exe-file.
  • The first item in sys.argv is the full pathname of the executable, the rest are the command line arguments.
  • sys.frozen only exists in the executable. It is set to "console_exe" for a console executable, to "windows_exe" for a console-less gui executable, and to "dll" for a inprocess dll server.
  • __file__ is not defined (you might want to use sys.argv[0] instead)

It is not apparent from those docs whether "the exe-file" and "the executable" are the same thing, and thus whether sys.executable and sys.argv[0] are the same thing. Looking at code that worked for both script.py and py2exe_executable.exe last time I had to do this, I find something like:

if hasattr(sys, 'frozen'):
    basis = sys.executable
else:
    basis = sys.argv[0]
required_folder = os.path.split(basis)[0]

As I say that worked, but I don't recall why I thought that was necessary instead of just using sys.argv[0].

Using only basis was adequate for the job in hand (read files in that directory). For a more permanent record, split something like os.path.realpath(basis).

Update Actually did a test; beats guesswork and armchair pontification :-)

Summary: Ignore sys.frozen, ignore sys.executable, go with sys.argv[0] unconditionally.

Evidence:

=== 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'])

=== results ===

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
于 2010-02-18T23:47:33.003 回答
9

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__))

干杯!

于 2013-07-04T09:50:43.647 回答
2

尝试这个:

import os
import sys
os.path.realpath(os.path.dirname(sys.argv[0]))
于 2010-02-18T22:35:22.477 回答
1

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

文件和exe的比较

于 2019-07-02T05:47:01.683 回答