Python共享对象模块命名规范
我写了一个用C++做的Python模块,并把它做成了一个共享库,运行得很好。不过在这个过程中,我通过一个叫strace的工具发现,Python在调用import
时,会寻找几种不同的文件名。具体来说,当我输入import foo
时,Python会按以下顺序查找:
- foo(一个文件夹)
- foo.so
- foomodule.so
- foo.py
- foo.pyc
这些都挺好理解的,除了foomodule.so这个名字。为什么Python会同时查找名字以.so和module.so结尾的文件呢?这是历史遗留问题吗?我查了很多资料,但没有找到任何解释,现在我在想,我是不是应该把我的模块命名为foomodule.so,而不是foo.so。我的系统里似乎有一些Python模块是用这两种命名方式的,所以我不禁想知道,这些不同的名字是否有什么特别的含义。
2 个回答
这只是我的猜测,但我认为这和下面的内容有关,来自于用C或C++扩展Python。
首先,创建一个名为spammodule.c的文件。(历史上,如果一个模块叫做spam,那么包含其实现的C文件就叫spammodule.c;如果模块名很长,比如spammify,那么这个模块的文件名可以简化为spammify.c。)
我想这个命名规则也适用于.so
文件的名称。这个猜测在同一文档的1.5节中得到了进一步的支持。
根据Wladimir的出色发现,我找到了module.so
作为后缀的首次引用。这是一个补丁,用于支持SunOS库的动态加载,来自“Bill”。(是Bill Jansson吗?)显然,module
作为后缀的命名规则在使用.so
共享库之前就已经开始了,当.so
库被采用时,这个规则就被继续沿用了。
不过我觉得Wladimir是对的——有趣的变化是采用了短模块名的规则。这也证实了我之前的猜测,即长模块名是早期的命名规则。
其实这跟平台有关,Python会根据不同的操作系统尝试不同的后缀。下面是import.c
文件中后缀表的初始化部分:
#ifdef HAVE_DYNAMIC_LOADING
memcpy(filetab, _PyImport_DynLoadFiletab,
countD * sizeof(struct filedescr));
#endif
memcpy(filetab + countD, _PyImport_StandardFiletab,
countS * sizeof(struct filedescr));
filetab[countD + countS].suffix = NULL;
_PyImport_Filetab = filetab;
这里面有两个列表,分别是_PyImport_DynLoadFiletab
和_PyImport_StandardFiletab
。后者比较简单,它在同一个文件中定义为[".py", ".pyw", ".pyc"]
(第二个后缀只有在Windows上才有)。_PyImport_DynLoadFiletab
则是在不同的dynload_<platform>.c
文件中定义的。在基于Unix的系统中,它的值是[".so", "module.so"]
;在CygWin上,它定义为[".dll", "module.dll"]
;而在OS/2上是[".pyd", ".dll"]
,在Windows上则简单地是[".pyd"]
。
我查了一下源代码的历史,发现1999年有个改动,似乎是添加了"module.so"作为一个可能的后缀:http://hg.python.org/cpython-fullhistory/diff/8efa37a770c6/Python/importdl.c。这个改动最初是为了NeXTStep(后来变成了Mac OS X)做的,主要是针对特定的链接设置。我对这个操作系统不太了解,所以不太清楚为什么要这样做——我猜是为了避免命名冲突。例如,一个框架库foo.so
可能已经被加载,而操作系统不允许加载同名的另一个库。所以foomodule.so
是一个折衷方案,允许名为foo
的Python模块存在。
编辑:上面的段落是错的——我没有追溯到足够早的历史,感谢senderle的指正。实际上,比较有趣的改动是出现在1994年的这个链接:http://hg.python.org/cpython-fullhistory/diff/2230/Python/import.c,在这里添加了一种新的模块命名方案(foo.so
),作为旧方案(foomodule.so
)的替代。我猜旧的命名方式在某个时候被弃用了,因为在多次重写代码时,某些平台(如Windows)已经移除了对它的支持。值得注意的是,即使在最初引入时,短模块名的版本也是排在前面的——这意味着它已经是首选的变体。
编辑2:我查了一下1994年的邮件列表/新闻组,看看这个改动是否有讨论过——看起来并没有,Guido van Rossum似乎是在没有告知任何人的情况下实现了这个改动。