Python app which reads and writes into its current working directory as a .app/exe

a 夏天 提交于 2019-12-06 04:39:37

A .app on the Mac doesn't have any reasonable current working directory when launched.

Of course it has some working directory, and you can easily find out what it is at runtime by os.getcwd(), and you can test on a variety of different ways of launching on different versions of OS X to figure out all of the patterns, but what good does that do you?

The good news is, you apparently don't actually want the current working directory; you need the directory of the .app bundle or .exe.

In other words, if someone does this:

C:\Users\foo> C:\Stuff\MyProgram.exe

You want C:\Stuff (the executable's directory), not C:\Users\foo (the working directory).

On Windows, this is easy. An .exe is just a file, and its path will be the __path__ you get in Python, so:

import os
pathToApp = os.path.dirname(__path__)

On Mac, it's harder. A .app is a bundle—a directory containing other files and directories. Somewhere in there is an executable interpreter and a copy of your script, and __path__ is going to give you the latter, not the path to the .app.

The correct way to get that is to use Cocoa (or CoreFoundation):

import Cocoa
pathToApp = Cocoa.NSBundle.mainBundle().bundlePath()

If you don't want to do that, you pretty much have to rely on some information that the documentation says you can't rely on and could change some day. But the following code should be safe:

import os
pathToApp = __file__
while not pathToApp.endswith('.app'):
  path = os.path.dirname(path)

In order for this to stop working, either the script would have to be outside the .app bundle, or inside another .app inside the one you're looking for, or bundles would have to stop being named .app, or they'd have to stop being structured as normal directories; none of this seems likely to change in OS X 10.*, or even OS Y 11.

As a side issue: what you're trying to do is most likely a bad idea in the first place. A Mac application shouldn't be working with files alongside it. Conversely, if users are going to expect to work on files alongside it, you probably want a simple Unix executable (or just a plain Python script with chmod +x), not an application.

Use the __file__ variable. This will give you the filename of your module. Using the functions in os.path you can determine the full path of the parent directory of your module. The os.path module is in the standard python documentation, you should be able to find that.

Then you can combine the module path with your filename to open it, using os.path.join.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!