py2exe和文件系统

时间:2009-10-02 19:49:56

标签: python configuration file py2exe

我有一个Python应用程序。它加载配置文件(和各种其他文件) 做的事情如:

_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
CONFIG_DIR = os.path.join(_path, 'conf')

这很好用。但是,当我用py2exe打包应用程序时,会发生不好的事情:

  File "proj\config.pyc", line 8, in <module>
WindowsError: [Error 3] The system cannot find the path specified: 'C:\\proj\
\dist\\library.zip\\conf'

显然,这是一条无效的道路......这样做的更有效方法是什么?我不 想要在程序中指定绝对路径,因为它可以放在不同的路径中 文件夹。我应该说“如果它说文件夹名称是'library.zip',那就去吧 再下一级到'dist'文件夹“?

请注意,我有非常嵌套的目录层次结构...例如,我有 一个模块gui.utils.images,存储在“gui / utils / images.py”中,它使用它的路径 例如,访问“gui / images / ok.png”。现在是py2exe版本 会尝试访问“proj / dist / library.zip / gui / images / ok.png”等等, 这是行不通的。

5 个答案:

答案 0 :(得分:10)

执行此类操作的常用方法(如果我理解正确的话)是这样的:

  1. 检查sys.frozen,py2exe设法设置,使用类似getattr(sys,'frozen','')
  2. 如果没有设置,请使用常用方法,因为您从源代码
  3. 运行
  4. 如果已设置,请检查sys.executable,因为这会指向.exe所在的位置(而不是python.exe所在的位置,这是它通常指向的位置)。使用类似os.path.dirname(sys.executable)的东西,然后将其与您的相对路径连接以查找子文件夹等
  5. 示例:

    frozen = getattr(sys, 'frozen', '')
    
    if not frozen:
        # not frozen: in regular python interpreter
        approot = os.path.dirname(__file__)
    
    elif frozen in ('dll', 'console_exe', 'windows_exe'):
        # py2exe:
        approot = os.path.dirname(sys.executable)
    
    elif frozen in ('macosx_app',):
        # py2app:
        # Notes on how to find stuff on MAC, by an expert (Bob Ippolito):
        # http://mail.python.org/pipermail/pythonmac-sig/2004-November/012121.html
        approot = os.environ['RESOURCEPATH']
    

    或其中的一些变体......后者处理py2app的使用。如果需要,您可以为其他构建器扩展它。

答案 1 :(得分:2)

您如何为所有包含的文件使用相对路径?我想应该可以使用sys.path.append(".." + os.path.sep + "images")作为关于ok.png的示例,然后你就可以open("ok.png", "rb")。使用相对路径应该解决py2exe生成的library.zip文件的问题,至少这是它对我的作用。

答案 2 :(得分:2)

从py2exe应用程序使用os.path.dirname(os.path.abspath(sys.argv [0])),它将以与python脚本相同的方式工作(因此您可以在不创建exe的情况下进行测试时间)和exe。

这比使用相对路径要好得多,因为您不必担心应用程序(.py或.exe)的运行位置。

答案 3 :(得分:2)

这是我的解决方案(在Windows,Linux和Mac上测试过)。如果通过符号链接启动应用程序或Python脚本,它也可以工作。

# Get if frozen
is_frozen = bool( getattr(sys, 'frozen', None) )

# Get path variable
path = sys.path if is_frozen else sys.argv

# Get nonempty first element or raise error
if path and path[0]:
    apppath = path[0]
elif is_frozen():
    raise RuntimeError('Cannot determine app path because sys.path[0] is empty.')
else:
    raise RuntimeError('Cannot determine app path in interpreter mode.')

# Make absolute (eliminate symbolic links)
apppath = os.path.abspath( os.path.realpath(apppath) )

# Split and return
appdir, appname = os.path.split(apppath)

答案 4 :(得分:0)

我在windows中使用以下技巧 当程序在py2exe可执行文件中冻结时#39; (即 my_application.exe ),dirname(__file__)返回运行主python脚本的文件夹。 奇怪的是,该文件夹不是包含 my_application.exe my_application.exe 本身的文件夹。
请注意, my_application.exe 不是二进制文件,而是包含python库和编译脚本的压缩文件夹(可以解压缩)。
这就是为什么os.path.dirname的{​​{1}}实际上是 my_application.exe 的原因。

因此,此代码为您提供了配置文件或映像的根目录(如果是冻结的应用程序,则包含py2exe可执行文件的文件夹,否则是运行python脚本的文件夹):

__file__

显然,您可以使用更通用的可移植方法来检测文件是否被冻结,因为其他答案显示而不是dirname = os.path.dirname(__file__) if dirname.endswith('.exe'): dirname = os.path.split(dirname)[0] 方法。