没有__init__的Python包
我用 pip install
安装了一个叫 flufl.enum 的Python包,发现它居然可以正常工作,尽管缺少了像普通Python包那样的 flufl/__init__.py
模块。这真是太奇怪了:
>>> import flufl
>>> flufl
<module 'flufl' (built-in)>
我尝试自己复现这个情况,创建了 foo/bar/__init__.py
,但没有 foo/__init__.py
,结果(果然) import foo
失败了。那 flufl
是怎么做到的呢?
3 个回答
0
flufl 只是一个命名空间包,它在 egg 的 namespace_packages.txt 文件中被声明。
如果你查看它的源代码树,你会发现里面确实有 flufl/__init__.py
这个文件,但在作为 egg 分发的时候,由于 setuptools 的一些特殊处理,这个文件似乎并不是必须的。
0
我不太明白这个。
ls /Users/sbo/lib/python2.7/site-packages/flufl.enum-3.2-py2.7.egg/flufl/
__init__.py __init__.pyc enum/
你是不是把 flufl.enum 和 Python 一起编译了?这是它成为内置模块的唯一方法。
顺便说一下,我确实看过一个 PEP(Python 的提案),里面提到过包可以跳过初始化,但我不记得这个提案是被批准了、拒绝了,还是正在审查中。
19
这个神奇的事情发生在一个叫做 flufl.enum-3.2-py2.7-nspkg.pth 的文件里,这个文件是通过 "pip install" 命令放到 site-packages 里的:
import sys,new,os
p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('flufl',))
ie = os.path.exists(os.path.join(p,'__init__.py'))
m = not ie and sys.modules.setdefault('flufl',new.module('flufl'))
mp = (m or []) and m.__dict__.setdefault('__path__',[])
(p not in mp) and mp.append(p)
pth 文件在程序启动时会被读取。特别是,这个文件会创建一个新的模块,叫做 "flufl",并把它放进 sys.modules 里。这也解释了为什么你会看到它被标记为 "内置":
>>> import new
>>> new.module('foo')
<module 'foo' (built-in)>