当前位置: 首页 > 知识库问答 >
问题:

NSTask没有以正确的路径启动Python

糜博远
2023-03-14

在我的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一起使用的版本,它返回:

[“/用户/...脚本路径.../内容/资源“,”/库/框架/Python.framework/Versions/2.7/lib/python27.zip“,”/库/框架/Python.framework/Versions/2.7/lib/python2.7“, ”/库/框架/Python.framework.framework/Versions/2.7/lib/python2.7/plat-Darwin“,”/库/框架/Python.framework/Versions/2.7/python2.7/plat-mac“, ”/库/框架/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpack“, ”/库/框架/Python.framework/Versions/2.7/lib/python2.7/lib-tk“, ”/库/框架/Python.framework/Versions/Versions/2.7/python2.7/lib-old“,”/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload“, ”/User/tatiana/Library/Python/2.7/lib/python/site-packages“, ”/Library/Python/2.7/python/2.7/site-packages“, ”/Library/Python/2.7/site-packages“]

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

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

如果我不设置任务环境,并且在Python测试中使用sys.可执行文件,我得到:

/库/框架/蟒蛇框架/版本/2.7/资源/蟒蛇.app/内容/MacOS/蟒蛇

...所以看起来它没有使用我的框架。如果将任务环境设置为:

// pythonEnv = [[[NSBundle mainBundle] privateFrameworksPath] stringByAppendingPathComponent:@"Python.framework/Versions/2.7/bin/python"];
NSDictionary *environment = [NSDictionary dictionaryWithObjectsAndKeys: pythonEnv, @"PYTHONPATH", nil];
[task setEnvironment:environment];

并测试它,我仍然得到相同的结果。但是,如果在蟒蛇中,我使用os.environ[“PYTHONPATH”]进行测试,我得到:

/用户/塔蒂亚娜/桌面/MyApp.app/内容/框架/蟒蛇.框架/版本/2.7/垃圾/蟒蛇

这看起来更有希望,但我很困惑为什么sys.executable没有给我这个。

更新2

我的 bin/python 不是可执行文件,所以我把它改成了 python2.7;系统可执行文件仍然显示它默认为库/...

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

共有2个答案

薛宜
2023-03-14

这可能是一个已知的错误。请参阅此旧邮件列表帖子以及 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进程中的< code>argv[0]只是< code >“python”。如果注释中提到的< code > _ NSGetExecutablePath hack失败或在您的版本中不存在,Python将查看< code>$PATH并尝试找到Python解释器的绝对路径。您的框架不在< code>$PATH中,它会被忽略,所以它会找到系统Python并使用它。

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

如果这确实是问题所在,解决方法是获取一个适当的 argv[0] 集合。我没有看到使用NSTask做到这一点的方法,所以你的下一个最佳选择可能是在PATH环境变量中包含Python框架的bin /的路径。至少这样,蟒蛇可能会推断出系统执行的正确值。

或者,如果您的脚本中没有真正关心< code>sys.executable的内容,您可以在确定您的Python实际上是正在执行的Python之后,让它保持原样,显示< code>sys.executable。

艾修然
2023-03-14

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

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

要设置NSTask运行的Python可执行文件的路径,请设置其LaunchPath。在Python中,您可以使用sys.executable访问该值。

要操作Python的搜索路径,调用-[NSTask setTechnology:]并将PYTHONPATH设置到框架的lib/python2.7文件夹。在Python中,您可以使用sys.path访问该路径。

 类似资料:
  • 谁能建议我该怎么做才能绕过这个问题?我以为Spring会把第一个破折号之前的任何东西作为ID,把后面的任何东西作为名称,但事实并非如此。 如果我使用/product/1-name执行GET,它工作得很好。如果path变量包含破折号,这似乎是一种奇怪的行为。 谢谢

  • 我有一个有一些订单的客户列表,我把他们都显示在一个表中。我添加了一个按钮,以便删除每个订单,如果需要的话。 当我试图删除一个特定的订单时,我会得到以下错误 未能将类型“java.lang.String”的值转换为所需类型“java.lang.Long”;嵌套异常是java.lang.NumberFormatException:对于输入字符串:“{cid}(cid=${customer.id})”

  • 问题内容: 我的React项目中的图片有问题。的确,我一直认为src属性的相对路径是建立在文件架构上的 这是我的文件架构: 但是我意识到路径是建立在URL上的。在我的一个组件中(例如到file1.jsx中),我有这个: 如何解决这个问题?我希望在react-router处理的任何形式的路由中,所有图像都可以使用相同的路径显示。 问题答案: 您使用的是相对网址,相对于当前网址,而不是文件系统。您可以

  • 我有一些问题,我的图像在我的反应项目。事实上,我一直认为进入src属性的相对路径是建立在文件体系结构上的 这里是我的文件体系结构: 然而,我意识到路径是建立在URL上的。在我的一个组件(例如file1.jsx)中,我有以下内容: 怎么可能解决这个问题呢?我希望在react-router处理的任何形式的路由中,所有图像都可以用相同的路径显示。

  • 我尝试执行一个jar xuggle-xuggler.jar,但出现以下错误(我在jar目录中使用java-jar命令执行): 清单-版本:1.0 Ant-版本:Apache Ant 1.8.2 创建人:1.6.0_23-B23(Sun Microsystems Inc.) 实施-供应商:www.xuggle.com 实施-标题:xuggle-xuggler 实施-版本:5.4.0 主类:com.x

  • 问题内容: 我知道有很多类似或相同的问题,但是我仍然无法理解/找到正确的方法来使用模块。Python是我最喜欢的语言,除使用导入外,我喜欢其中的所有内容:递归导入(当您尝试引用尚不存在的名称时),导入路径等。 因此,我有这种项目结构: 可以用作独立单位,但也应由导入。我现在在做什么,例如,在我编写中,即使用导入模块的完整路径。我这样做是因为,如果我使用-当从另一个包()中导入该模块时,它将不起作用