在我的Mac OS应用程序中,我包含了一个Python.framework(v 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 / Version / 2.7 / lib / python27.zip”,“/ Library / Frameworks / Python.framework / Versions / 2.7 / lib / python2.7“,”/ Library / Frame /Python.framework / Version / 7.7 / lib / python2.7 / plat-Darwin“,”/ Library / Frame /Python.framework /版本/ 2.7 / lib / python2.7 / plat-mac“,”/ Library / Frame /Python.framework / Version / 7.7 / lib / python2.7 /plat-make / lib -scriptpackages“,”/ Library / Frameworks / Python.framework / Versions / 2.7 / lib / python2.7 / lib-tk“,”/ Library / Frameworks / Python.framework / Version / 7.7 / lib / python2.7 / lib -old“,”/ Library / Frameworks / Python.framework / Versions / 2.7 / lib / python2.7 / lib-dynload“,”/ Users / tatiana / Library /Python / 2.7 / lib / python / site-packages“,”/ Library / Frame /Python.framework /版本/ 2.7 / lib / python2.7 / site-packages“,”/ Library /Python / 2.7 / site-package“]
...它没有使用我所包含的框架。我还应该在哪里设置正确的路径?它是构建设置中的东西我忘记了吗?
更新1 ------------------------
如果我没有设置任务环境,并且在使用sys.executable
的Python测试中,我得到:
/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
...所以看起来它没有使用我的框架。如果设置任务环境:
// pythonEnv = [[[NSBundle mainBundle] privateFrameworksPath] stringByAppendingPathComponent:@"Python.framework/Versions/2.7/bin/python"];
NSDictionary *environment = [NSDictionary dictionaryWithObjectsAndKeys: pythonEnv, @"PYTHONPATH", nil];
[task setEnvironment:environment];
并测试它,我仍然得到相同的结果。但是,如果在Python中我使用os.environ["PYTHONPATH"]
进行测试,我得到:
/Users/tatiana/Desktop/MyApp.app/Contents/Frameworks/Python.framework/Versions/2.7/bin/python
这看起来有点让人失望,但我很困惑为什么sys.executable没有给我这个。
更新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];
答案 0 :(得分:0)
听起来你混淆了两件相关的事情:
要设置NSTask
运行的Python可执行文件的路径,请设置其launchPath
。在Python中,您可以使用sys.executable
访问该值。
要操纵Python的搜索路径,请调用-[NSTask setEnvironment:]
并将PYTHONPATH
设置为您框架的lib/python2.7
文件夹。在Python中,您可以使用sys.path
访问该路径。
答案 1 :(得分:0)
这可能是一个已知的错误。请参阅此old mailing list post和此much more recent bug on bugs.python.org。
在Python 2.7.3的Modules / getpath.c中有这样的评论:
/* On Mac OS X, if a script uses an interpreter of the form
* "#!/opt/python2.3/bin/python", the kernel only passes "python"
* as argv[0], which falls through to the $PATH search below.
* If /opt/python2.3/bin isn't in your path, or is near the end,
* this algorithm may incorrectly find /usr/bin/python. To work
* around this, we can use _NSGetExecutablePath to get a better
* hint of what the intended interpreter was, although this
* will fail if a relative path was used. but in that case,
* absolutize() should help us out below
*/
虽然这可能不适用于您,但这是一个提示,执行的python进程中argv[0]
可能只是"python"
。然后,如果注释中提到的$PATH
hack失败或您的版本中没有,则Python将查看_NSGetExecutablePath
并尝试查找Python解释器的绝对路径。您的框架(不在$PATH
中)将被忽略,因此它会找到系统Python并使用它。
您可以通过几种方式验证这一点。您可以在调试器中设置断点,并查看NSTask
最终传递给exec()
的参数。或者,您可以查看ps ax
并找到您的Python进程(可能有助于让您的脚本打印其PID然后永远运行)并查看第一个参数是否是框架的完整路径。或者,您可以在脚本中查看sys.argv[0]
(可能 - 可能已修改)。
如果这确实是问题,那么解决方法是获得正确的argv[0]
设置。我没有看到使用NSTask
的方法,所以你最好的选择可能是在bin/
环境变量中包含Python框架PATH
的路径。至少Python可以推断出sys.executable
的正确值。
或者,如果您的脚本中没有任何内容真正关心sys.executable
,那么在确定您的Python实际上是正在执行的Python之后,您可以保留原样,发送sys.executable
。