我从未注意到今天之前在我的一些软件包中定义的__path__
属性。根据文档:__path__对于什么有用?
软件包支持一个更特别的 属性,
__path__
。这是 已初始化为包含 的列表,其中包含 程序包的__init__.py
之前的代码 的目录的名称被执行。这个 变量可以被修改;这样做 影响将来搜索模块 和包含在 包中的子包。虽然此功能通常不需要 ,但它可用于扩展包中的 模块集。
有人可以向我解释这是什么意思,为什么我会想要使用它?
我从未注意到今天之前在我的一些软件包中定义的__path__
属性。根据文档:__path__对于什么有用?
软件包支持一个更特别的 属性,
__path__
。这是 已初始化为包含 的列表,其中包含 程序包的__init__.py
之前的代码 的目录的名称被执行。这个 变量可以被修改;这样做 影响将来搜索模块 和包含在 包中的子包。虽然此功能通常不需要 ,但它可用于扩展包中的 模块集。
有人可以向我解释这是什么意思,为什么我会想要使用它?
这通常与pkgutil用来让一个封装在磁盘进行布局。例如,zope.interface和zope.schema是独立的发行版(zope
是“命名空间包”)。您可能在/usr/lib/python2.6/site-packages/zope/interface/
中安装了zope.interface,而您在本地更多地使用了zope.schema(/home/me/src/myproject/lib/python2.6/site-packages/zope/schema
)。
如果你把pkgutil.extend_path(__path__, __name__)
在/usr/lib/python2.6/site-packages/zope/__init__.py
那么这两个zope.interface和zope.schema将导入的,因为pkgutil将不得不['/usr/lib/python2.6/site-packages/zope', '/home/me/src/myproject/lib/python2.6/site-packages/zope']
变化__path__
。
pkg_resources.declare_namespace
(Setuptools的一部分)与pkgutil.extend_path
类似,但更清楚路径上的拉链。
手动更改__path__
并不常见,可能不是必需的,但在调试名称空间包的导入问题时查看变量很有用。
import os
stdlib_dir = os.path.dirname(os.__file__)
real_distutils_path = os.path.join(stdlib_dir, 'distutils')
__path__.append(real_distutils_path)
execfile(os.path.join(real_distutils_path, '__init__.py'))
# and then apply some monkeypatching here...
如果更改__path__
,您可以强制解释在不同的目录去寻找属于那个包的模块。
这将允许你,例如,加载不同版本的基础上运行时条件相同的模块。如果你想在不同平台上使用相同功能的不同实现,你可能会这样做。
Django使用这个在启动时动态地加载django-admin.py命令! '命令= {名称:'django.core'在find_commands(__ path __ [0])中的名称}} – 2014-05-10 18:46:23
除了选择不同版本的基础上运行时条件模块的句法说,这个功能也可以让您将包分解成多个部分/下载/同时保持单个逻辑封装的外观安装。
请考虑以下情况。
mypkg
和_mypkg_foo
。_mypkg_foo
包含可选模块mypkg
,foo.py
。mypkg
不包含foo.py
。mypkg
的__init__.py
可以做一些事情,像这样:
try:
import _mypkg_foo
__path__.append(os.path.abspath(os.path.dirname(_mypkg_foo.__file__)))
import mypkg.foo
except ImportError:
pass
如果有人已经安装的软件包_mypkg_foo
,则mypkg.foo
是提供给他们。如果他们没有,它不存在。
具体情况我遇到是当一个包:
您还可以使用__path__
为的monkeypatching,例如,我已经通过创建一个文件distutils/__init__.py
,早期是sys.path
monkeypatched在时间的distutils变得足够大,我想将它的部分分割成子目录,而不必更改任何引用它的代码。
例如,我有一个名为views
的软件包,它正在收集许多支持的实用程序函数,这些函数与包的主要顶级目的混淆。我能够把这些配套功能移进子目录utils
并添加以下行__init__.py
为views
包:
__path__.append(os.path.join(os.path.dirname(__file__), "utils"))
随着这一变化也views/__init_.py
,我可以在新文件运行该软件的其余部分结构,而不需要对文件做进一步的修改。
(我试图做的views/__init__.py
文件import
语句类似的东西,但子包模块仍然不可见通过view
包的进口 - 我不能完全肯定,如果我想的东西有;上欢迎评论)
(基于Python 2.7版安装)这种反应
我有一种感觉,它与命名空间包有关,但我在拼凑它的工作方式时遇到了问题。谢谢! – 2010-04-27 20:36:03