在OS X上追踪互联的Python可执行文件

1 投票
2 回答
686 浏览
提问于 2025-04-16 09:46

我有一个比较长的背景介绍,然后最后有三个问题。

在OS X系统中,系统自带的Python框架里有三个可执行文件(我给它们起个简单的名字):

> F=/System/Library/Frameworks/Python.framework/Versions/2.6
> A=$F/bin/python2.6
> B=$F/Resources/Python.app/Contents/MacOS/Python
> C=$F/Python

$A和$B显然太小,不可能是Python本身。

> ls -s $A; ls -s $B; ls -s $C
16 /System/Library/Frameworks/Python.framework/Versions/2.6/bin/python2.6
16 /System/Library/Frameworks/Python.framework/Versions/2.6/Resources/Python.app/Contents/MacOS/Python
3152 /System/Library/Frameworks/Python.framework/Versions/2.6/Python

> $A
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) 
> $B
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) 
> $C
-bash: /System/Library/Frameworks/Python.framework/Versions/2.6/Python: cannot execute binary file

尽管这三个文件的大小和效果看起来差不多,但前两个其实是不同的,比如:

> cmp -lc $A $B

另外,在/usr/bin目录下,python2.6是指向$C的一个符号链接,但那里还有:

> D=/usr/bin/python
> ls -s $D
48 /usr/bin/python

我想搞清楚它们之间是怎么联系的;不过用which这个命令查不出什么。

> export DYLD_PRINT_LIBRARIES=1
> $A
..
dyld: loaded: /System/Library/Frameworks/Python.framework/Versions/2.6/Resources/Python.app/Contents/MacOS/Python
dyld: loaded: /System/Library/Frameworks/Python.framework/Versions/2.6/Python

总结一下:$A加载$B,然后是$C;$B加载$C;$D加载$B,然后是$C。

所以我有以下三个问题:

  1. 这些内容有文档说明吗?
  2. 这些文件各自有什么作用?
  3. 最重要的是,有哪些工具可以帮助追踪这些连接关系?

2 个回答

2

这里要用到的工具是 ls 和 file。

使用 ls -l 命令可以查看符号链接指向的目标。符号链接的大小是它所指向路径中字符的数量。

用 file x 命令可以查看文件的类型。

举个例子:

file /System/Library/Frameworks/Python.framework/Versions/2.6/Python  
/System/Library/Frameworks/Python.framework/Versions/2.6/Python: Mach-O universal binary with 3 architectures  
/System/Library/Frameworks/Python.framework/Versions/2.6/Python (for architecture x86_64):      Mach-O 64-bit dynamically linked shared library x86_64  
/System/Library/Frameworks/Python.framework/Versions/2.6/Python (for architecture i386):        Mach-O dynamically linked shared library i386  
/System/Library/Frameworks/Python.framework/Versions/2.6/Python (for architecture ppc7400):     Mach-O dynamically linked shared library ppc  

OSX 的框架在 苹果开发文档 中有描述。

/Library/Frameworks/Python.framework/Versions/2.6/Resources/Python.app/Contents/MacOS/Python 和 /System/Library/Frameworks/Python.framework/Versions/2.6/bin/python2.6 是实际的 Python 解释器,我认为它们是指向同一个二进制文件的硬链接。

/usr/bin/python 是路径中的 Python,我觉得它是指向 /usr/bin/pythonw 的硬链接。这些是包装器,它们会调用 exec 来执行位于 /System/Library/Frameworks/Python.framework/Versions/2.6/bin/python2.6 的真实 Python 解释器,具体可以查看 Python bug 跟踪器

/System/Library/Frameworks/Python.framework/Versions/Current 是指向 /System/Library/Frameworks/Python.framework/Versions/2.6 的符号链接,使用的是标准的 OSX 框架版本管理方式。

/System/Library/Frameworks/Python.framework/Versions/2.6/Python 是一个共享库,负责所有的工作——它被设置为库,这样你就可以用其他语言编写程序来嵌入 Python 解释器。

想了解更多细节,可以查看 Python 文档,但我怀疑你可能需要在 苹果 Python 邮件列表 中搜索相关信息。

3

在OS X 10.6中,苹果提供的Python是通过标准的Python 框架构建和安装的,虽然做了一些定制的调整。这个信息没有出现在苹果的文档中,因为这种特定的布局并不是苹果自己发明的,而是Python项目在多年来使用其他OS X框架布局作为基础逐步演变而来的。如果你使用python.org的安装程序在OS X上安装Python,比如从这里下载,你会发现同样的模式,只不过框架的根目录是在/Library/Frameworks/而不是/System/Library/Frameworks。所以,如果你真的感兴趣,可以下载源代码,看看configure脚本和Makefile模板。不过,这可能会比较难懂。苹果还在这里提供了用于构建每个OS X版本中开源组件(包括Python)的源代码和定制补丁,因此理论上你可以看到苹果是如何构建它们发布的内容的。

那么,针对你的问题,在Python 2.6中:

$A是pythonw的包装器,它确保Python被OS X识别为一个图形用户界面(GUI)应用程序(可以查看pythonw.c的源代码,链接在这里)。需要注意的是,苹果版本的pythonw经过定制,增加了首选的执行模式(可以查看苹果的man 1 python)。在更新版本的Python(2.7和3.2)中,采用了稍微不同的方法。

$B是Python解释器的实际可执行文件。它是由pythonw可执行文件$A执行的。你可以通过实际运行Python并查看sys.executable的值来轻松验证这一点,但苹果提供的Python 2.6存在一个bug(可能是由于上面提到的新增功能),导致这个值被错误地赋值。python.org的Python 2.6.6显示了正确的值:

$ cd /Library/Frameworks/Python.framework/Versions/2.6
$ ./bin/python2.6 -c 'import sys;print(sys.executable)'
/Library/Frameworks/Python.framework/Versions/2.6/Resources/Python.app/Contents/MacOS/Python`

$C是包含所有可加载模块的共享库。你可以通过在$B上使用otool来查看这一点:

$ cd /System/Library/Frameworks/Python.framework/Versions/2.6
$ cd Resources/Python.app/Contents/MacOS/
$ otool -L ./Python
Python:
   /System/Library/Frameworks/Python.framework/Versions/2.6/Python (compatibility version 2.6.0, current version 2.6.1)
   /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)

撰写回答