NSTask未使用正确的路径启动Python

2024-05-15 02:57:42 发布

您现在位置:Python中文网/ 问答频道 /正文

在我的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];

Tags: 脚本框架应用程序taskbinliblibraryframework
2条回答

听起来你好像混淆了两件相关的事情:

  1. 启动应用程序包中的Python可执行文件
  2. 设置Python搜索路径以包含应用程序包中的Python lib文件夹

要设置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中有这样一条注释:

 /* 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"。然后,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之后,可以保持原样。在

相关问题 更多 >

    热门问题