0

在我的 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/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", "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages", "/Library/Frameworks/Python.framework /Versions/2.7/lib/python2.7/lib-tk”、“/Library/Frameworks/Python.framework/Versions/2.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/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages", "/Library/Python/2.7/site-packages"]

...它没有使用我包含的框架。我还应该在哪里设置正确的路径?我忘记了构建设置中的内容吗?

更新 1 ---------------------

如果我没有设置任务环境,并且在 Python 测试中sys.executable,我得到:

/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];
4

2 回答 2

0

这可能是一个已知的错误。在 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
  */

虽然这可能并不直接适用于您,但这是一个提示,可能argv[0]在执行的 python 进程中只是"python". 如果注释中提到的 hack 失败或您的版本中不存在,Python 将查看$PATH并尝试找到 Python 解释器的绝对路径。_NSGetExecutablePath您的框架(不在 中$PATH)被忽略,因此它会找到系统 Python 并使用它。

您可以通过几种方式验证这一点。您可以在调试器中设置断点并查看NSTask最终传递给exec(). 或者,您可以查看ps ax并找到您的 Python 进程(让您的脚本打印其 PID 然后永远运行可能会有所帮助)并查看第一个参数是否是您的框架的完整路径。或者,您可以sys.argv[0]在您的脚本中签出(可能——也许它已被修改)。

如果这确实是问题所在,则解决方法是获得适当的argv[0]设置。我看NSTask不出bin/PATH. 至少 Python 可以推断出正确的值sys.executable

或者,如果您的脚本中没有任何内容真正关心sys.executable,那么您可以在确定您的 Python 实际上是正在执行的那个之后将其保持原样,尽管sys.executable.

于 2013-01-03T13:36:38.720 回答
0

听起来你混淆了两个相关的事情:

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

要设置NSTask运行的 Python 可执行文件的路径,请设置其launchPath. 在 Python 中,您可以使用sys.executable.

要操作 Python 的搜索路径,请-[NSTask setEnvironment:]使用PYTHONPATHset调用框架的lib/python2.7文件夹。在 Python 中,您可以使用sys.path.

于 2012-12-27T00:52:00.947 回答