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”,或者其他东西, 这是行不通的。
I have a Python app. It loads config files (and various other files) by
doing stuff such as:
_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
CONFIG_DIR = os.path.join(_path, 'conf')
This works fine. However, when I package the app with py2exe, bad things happen:
File "proj\config.pyc", line 8, in <module>
WindowsError: [Error 3] The system cannot find the path specified: 'C:\\proj\
\dist\\library.zip\\conf'
Obviously that's an invalid path... What's a more robust way of doing this? I don't
want to specify absolute paths in the program because it could be placed in different
folders. Should I just say "if it says the folder name is 'library.zip', then go
one more level down to the 'dist' folder"?
Note that I have pretty nested directory hierarchies... for example, I have
a module gui.utils.images, stored in "gui/utils/images.py", and it uses its path
to access "gui/images/ok.png", for example. Right now the py2exe version
would try to access "proj/dist/library.zip/gui/images/ok.png", or something,
which just won't work.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
做这类事情的通常方法(如果我理解正确的话)是这样的:
示例:
或其某些变体...后一个处理 py2app 的使用。如果需要,您可以为其他构建器扩展此功能。
The usual approach to doing this sort of thing (if I understand properly) is this:
Example:
Or some variant thereof... the latter one handles the use of py2app. You could extend this for other builders, if needed.
这是我的解决方案(在 Windows、Linux 和 Mac 上测试)。如果应用程序或 Python 脚本通过符号链接启动,它也可以工作。
Here's my solution (tested on Windows, Linux and Mac). It also works if the application or Python script is started via a symbolic link.
您对所有包含的文件使用相对路径有何看法?我想应该可以使用
sys.path.append(".." + os.path.sep + "images")
作为关于 ok.png 的示例,然后你就可以打开(“ok.png”,“rb”)
。使用相对路径应该可以解决 py2exe 生成的library.zip 文件的问题,至少它对我来说是这样的。What do you think about using relative paths for all of the included files? I guess it should be possible to use
sys.path.append(".." + os.path.sep + "images")
for your example about ok.png, then you could justopen("ok.png", "rb")
. Using relative paths should fix the issues with the library.zip file that's generated by py2exe, at least that's what it does for me.从 py2exe 应用程序使用 os.path.dirname(os.path.abspath(sys.argv[0])) ,它将以与 python 脚本相同的方式工作(因此您可以进行测试,而无需每次都创建 exe)来自exe。
这比使用相对路径要好得多,因为您不必担心应用程序(.py 或 .exe)从哪里运行。
Use os.path.dirname(os.path.abspath(sys.argv[0])) from a py2exe app, it'll work the same way from the python script (so you can test without creating the exe every time) and from the exe.
This can be much better than using relative paths because you don't have to worry about where your app (.py or .exe) is running from.
我在 Windows 中使用以下技巧。
当程序冻结在 py2exe“可执行文件”(即 my_application.exe)中时,
dirname(__file__)
返回主 Python 脚本运行的文件夹。奇怪的是,该文件夹不是包含 my_application.exe 的文件夹,而是包含 my_application.exe 本身的文件夹。
请注意,my_application.exe 不是二进制文件,而是一个压缩文件夹(您可以解压缩它),其中包含 python 库和已编译的脚本。
这就是为什么
__file__
的os.path.dirname
实际上是 my_application.exe。因此,这段代码为您提供了配置文件或图像的根目录(如果是冻结的应用程序,则为包含 py2exe 可执行文件的文件夹,否则为运行 python 脚本的文件夹):
显然,您可以使用更通用的、可移植的方法来检测文件是否被冻结,如其他答案所示,而不是
endswith
方法。I use the following trick in windows.
When the program is frozen in a py2exe 'executable' (i.e my_application.exe),
dirname(__file__)
returns the folder where your main python script is running.Oddly enough, that folder is not the folder containing my_application.exe but my_application.exe itself.
Note that my_application.exe is not a binary file but a compressed folder (you can unzip it) that contains python libs and your compiled scripts.
That's why the
os.path.dirname
of your__file__
is in fact my_application.exe.Thus, this code gives you the root directory for your configuration files or images (in case of a frozen application, the folder containing the py2exe executable, otherwise the folder from where your python script is running):
Obviously you can use more general, portable methods to detect if the file is frozen as other answers show instead of the
endswith
method.