Question

I have a python script which reads a text file in it's current working directory called "data.txt" then converts the data inside of it into a json format for another separate program to handle.

The problem i'm having is that i'm not sure how to read the .txt file (and write a new one) which is in the same directory as the .app when the python script is all bundled up. The current method i'm using doesn't work because of something to do with it using the fact that it's ran from the terminal instead of executed as a .app?

Any help is appreciated!

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top