0

I'm trying to use NSTask to start a looping python script from a cocoa app. The python script ends up in the app's Contents/Resources folder.

I get the path to the script and create the NSTask with:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSString *scriptPath = [[NSBundle mainBundle] pathForResource:filename ofType:@"py"];
    NSTask* task = [[NSTask alloc] init];
    task.launchPath = PYTHON_PATH;
    task.arguments = [NSArray arrayWithObjects:scriptPath, nil];
    [task launch];
    [task waitUntilExit];
});

(I've omitted the stdOutPipe stuff for readability)

When I build & run my app from xcode it works as expected, the task holds at waitUntilExit and the python script runs continuously.

When I try to run this from the produced .app file it gets to waitUntilExit, stalls for awhile, and then exits with an error. I have logging in the python script so I know that no part of the script is run during this time. The script path is true to the location of the python scripts and returns the same path when run from xcode or from the .app.

I figure I must have some of the project settings set-up incorrectly, but it seems like its handling resources correctly. Any idea?

Update 1 Running a non-looping python script with just a print statement works for the .app. The followings non-looping script fails as well:

#!/usr/bin/python      
import os

def log(string):
    print(string)
    path = os.environ['PWD'] + '/smoke_screen_test.txt'
    f1=open(path, 'a')
    f1.write(string + "\n")

if __name__ == '__main__':
    log("Test works")
    exit(0)

Maybe the import statements mess it up? Or the file creation?

Dirk
  • 599
  • 1
  • 4
  • 18
  • 1
    Can a simple non-looping python script be run from the same path? – pkamb Apr 07 '17 at 18:19
  • @pkamb good question! The .app will execute without error for a non-looping python function. Does that tell you anything? – Dirk Apr 08 '17 at 17:59
  • @pkamb Actually I spoke to soon, a test non-looping script with just a print statement will execute in the .app, but the script in the update above will fail as well. – Dirk Apr 08 '17 at 18:38
  • I was mainly thinking you may be hitting something like a Sandbox violation when running **any** script from your app. [NSApplicationScriptsDirectory](http://stackoverflow.com/a/41710306/1265393) needed? – pkamb Apr 08 '17 at 19:04

1 Answers1

1

The problem was the use of os.environ['PWD']. PWD does not return the local directory of the script being executed. Duh. Solution is to grab the path of the script from argv[0] and use the directory of that path:

path = os.path.dirname(sys.argv[0])

Then pass path around as needed.

Dirk
  • 599
  • 1
  • 4
  • 18