在我的Mac OS应用程序中,我包含了一个Python.framework(2.7版),所以我根据需要将其添加到“链接框架”中。同样在应用程序中,我使用NSTask启动一个Python脚本,如下所示:
//...
pythonEnv = [[[NSBundle mainBundle] privateFrameworksPath] stringByappendingPathComponent:@"Python.framework/Versions/2.7/bin/python"];
task = [[NSTask alloc] init];
outPipe = [NSPipe pipe];
readHandle = [outPipe fileHandleForReading];
data = [[NSMutableData alloc] init];
args = [NSArray arrayWithObjects: scriptPath, kbt, server, port, username, password, nil];
[task setArguments:args];
[task setLaunchPath: pythonEnv];
readHandle = [outPipe fileHandleForReading];
[task setStandardInput:[NSPipe pipe]];
[task setStandardOutput:outPipe];
[task launch];
[task waitUntilExit];
//...
当我构建应用程序,并在Python脚本中检查它与sys.path
一起使用的版本时,它返回:
[“/Users/…脚本路径…/Contents/Resources”,”/Library/Frameworks/Python.framework/Versions/2.7/lib/python27.zip“,”/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7“,”/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat darwin“,”/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat mac“,“/库/框架/Python.framework/Versions/2.7/lib/python2.7/plat mac/lib scriptpackages“,”/lib/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib tk“,”/lib/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib旧“,”/lib/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib dynload“,“/Users/tatiana/Library/Python/2.7/lib/Python/site packages”,“/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site packages“,”/Library/Python/2.7/site packages“]
。。。它没有使用我的包含框架。我还应该在哪里设置正确的路径?是不是我忘记了一些构建设置?在
更新1-------------------
如果不设置任务环境,并且在使用sys.executable
的Python测试中,我得到:
/库/框架/Python.framework/Versions/2.7/资源/Python.app/Contents/MacOS/Python在
。。。所以看起来它没有使用我的框架。如果将任务环境设置为:
^{pr2}$测试一下,结果还是一样的。但是,如果在Python中使用os.environ["PYTHONPATH"]
进行测试,我得到:
/Users/tatiana/桌面/MyApp.app/Contents/Frameworks/Python.framework/Versions/2.7/bin/python
这看起来有点令人兴奋,但我不明白为什么系统可执行文件不是给我的。在
更新2
我的bin/python不是可执行文件,所以我将其改为python2.7;sys.executable
仍然显示它默认为Library/。。。在
pythonEnv = [[[NSBundle mainBundle] privateFrameworksPath] stringByAppendingPathComponent:@"Python.framework/Versions/2.7/bin/python2.7"];
NSString *searchPath = [[[NSBundle mainBundle] privateFrameworksPath] stringByAppendingPathComponent:@"Python.framework/Versions/2.7/lib/python2.7"];
NSDictionary *environment = [NSDictionary dictionaryWithObjectsAndKeys: searchPath, @"PYTHONPATH", nil];
[task setEnvironment:environment];
听起来你好像混淆了两件相关的事情:
要设置
NSTask
运行的Python可执行文件的路径,请设置其launchPath
。在Python中,可以使用sys.executable
访问该值。在要操作Python的搜索路径,调用
-[NSTask setEnvironment:]
,并将PYTHONPATH
设置为框架的lib/python2.7
文件夹。在Python中,可以使用sys.path
访问该路径。在这可能是已知的错误。看到这个old mailing list post和这个much more recent bug on bugs.python.org。在
python2.7.3的Modules/getpath.c中有这样一条注释:
虽然这可能不直接适用于您,但这是一个提示,在执行的python进程中,
argv[0]
可能只是"python"
。然后,Python将查看$PATH
,并尝试找到Python解释器的绝对路径,如果注释中提到的_NSGetExecutablePath
黑客失败或在您的版本中不存在。不在$PATH
中的框架被忽略,因此它找到系统Python并使用它。在你可以用几种方法来验证这一点。您可以在调试器中设置断点,并查看
NSTask
最终传递给exec()
的参数。或者,您可以查看ps ax
并找到Python进程(让脚本打印其PID然后永远运行可能会有帮助),并查看第一个参数是否是框架的完整路径。或者,您可以检查脚本中的sys.argv[0]
(可能已经修改)。在如果这确实是问题所在,解决方法是获得一个适当的
argv[0]
集。我看不到用NSTask
实现这一点的方法,所以下一个最佳选择可能是在PATH
环境变量中包含Python框架的bin/
的路径。至少Python可以推断出sys.executable
的正确值。在或者,如果脚本中没有任何内容真正关心
sys.executable
,那么在确定Python实际上是正在执行的Python之后,可以保持原样。在相关问题 更多 >
编程相关推荐