Python命名空间包
简单的理解,命名空间包是对相关的包或模块进行分组的一种方法,通常是一个被忽略的功能,它对于在较大的项目中构建打包生态系统非常有用。
如果你的应用组件的开发、打包和版本化都是独立的,但仍然希望从同一个命名空间访问它们,那么命名空间包特别有用,它有利于明确每个包所属的组织或项目。
例如,假设有一个 Acme 公司,该公司中使用共同的 acme 命名空间,同时创建通用的 acme 命名空间包作为该组织的其他包的容器。如果 Acme 公司中的某人想要向这个命名空间贡献一个与 SQL 相关的库,那么他需要在 acme 中注册自己新的 acme.sql 包,整个文件结构如下所示:
$tree acme/ acme/ ├───acme │ ├───__init__.py │ └───sql │ └──__init__.py └───setup.py 2 directories, 3 files
在此基础上,如果想添加一个新的子包,例如添加 templating,则需要将其包含在 acme 的源代码树中,如下所示:
$tree acme/ acme/ ├───acme │ ├───__init__.py │ ├───sql │ │ └──__init__.py │ └───templating │ └──__init__.py └───setup.py 3 directories, 4 files
仔细观察就会发现,采用这种方式几乎不可能单独开发 acme.sql 和 acme.templating。且 setup.py 脚本还必须指定每个子包的所有依赖,所以不可能(至少非常困难)选择性地安装 acme 中的部分组件。此外,如果某些子包的需求文件有冲突,是一个无法解决的问题。
通过利用命名空间包,我们可以单独保存每个子包的源代码树,如下所示:
$tree acme.sql/ acme.sql/ ├───acme │ └───sql │ └──__init__.py └───setup.py 2 directories, 2 files $tree acme.templating/ acme.templating/ ├───acme │ └───templating │ └──__init__.py └───setup.py 2 directories, 2 files
由此,就可以在 PyPI 或者使用的任何包索引中单独注册它们,用户还可以从 acme 命名空间中选择想要安装的子包,而无需安装通用的 acme 包,执行代码如下:
$pip install acme.sql acme.templating
注意,独立的源代码树不足以在 Python 中创建命名空间包,如果不想让包之间相互覆盖,就需要做一些额外的工作,此外,正确的处理方式也会随着 Python 版本的不同而有所不同。
隐式命名空间包如果你只使用 Python 3.x,也只面向 Python 3.x 的用户,则可以使用 PEP 420 引入的定义命令空间的新方法,即隐式命名空间包。它是标准路径的一部分,并从 Python 3.3 版本开始成为语言官方内容的一部分。
简单来说,对于每一个包含 Python 包或模块(也包括命名空间包)的目录来说,如果其不包含 __init__().py 文件,那么它就被看做是命名空间包。
例如,前面所说的 acme 在 Python 3.3 以及更高版本中,就是一个命名空间包。使用安装工具的最小 setup.py 脚本文件如下所示:
from setuptools import setup setup( name = acme.templating , packages = [ acme.templating ], )
但是,直到发表本节时,setuptools.find_packages() 还不支持 PEP 420,但这在未来很可能会改变。此外,要想实现命名空间包的简单继承,显示地定义包列表是值得的。
以前Python版本中的命名空间包Python 3.3 之前的版本中,虽无法使用 PEP 420 布局中的命名空间包,但仍可以使用它。旧版 Python 中,有几种方法可以将包定义成命名空间。
最简单的方法就是为每个组件创建一个文件结构,类似于没有命名空间包的普通包布局,并将所有事情都留给 setuptools。
因此,acme.sql 和 acme.templating 的布局示例可能如下所示:
$tree acme.sql/ acme.sql/ ├───acme │ ├──__init__.py │ └───sql │ └──__init__.py └───setup.py 2 directories, 3 files $tree acme.templating/ acme.templating/ ├───acme │ ├──__init__.py │ └───templating │ └──__init__.py └───setup.py 2 directories, 3 files
注意,acme.sql 和 acme.templating 都有一个额外的源代码文件 acme/__init__.py,这个文件必须是空的。
如果我们提供 acme 作为 setuptools.setup() 函数 namespace_package 关键字参数的值,那么将会创建如下的 acme 命名空间包:
from setuptools import setup setup( name = acme.templating , packages = [ acme.templating ], namespace_package = [ acme ], )
当然,最简单的方法不一定是最好的,为了注册一个新的命名空间,setuptools 将会在 __init__.py 文件中调用 pkg_resources.declare_namespace() 函数,即便 __init__.py 文件是空的也会调用。
无论如何,正如官方文档所说,你自己负责在 __init__.py 文件中声明命名空间,并且未来可能会删除 setuptools 的这个隐式行为。为了保证安全,也为了未来依然可用(future-proof),需要将下面这行代码添加到 acme/__init__.py 文件中:
__import__( pkg_resources ).declare_namespace(__name__)
23054.html
python相关文章
- Python 一网打尽<排序算法>之堆排序算法中的树
- [33]python Web 框架:Tornado
- 简述python变量的命名规则_Python 变量命名规则
- 符合python命名规范的标识符是什么_Python标识符命名规范
- python海龟绘图画圆_Python启蒙之海龟作图「建议收藏」
- Python元组_python输出元组
- 【说站】python unittest单元测试的过程
- Python udp编程_python socket udp
- python图像多层小波分解_Python中图像小波分解与重构以及灰度图加噪
- python attrs_Python attrs作用是什么?
- python中copy.deepcopy_Python eval
- Python win32api_python api文档
- python读取excel文件代码_python怎么加速读取excel
- 正则表达式Python_python正则表达式匹配字符串
- Python 插件虚拟环境支持
- Python 读写SVG ns0命名空间
- Python if elif else语句:if elif else组合语句用法及注意事项
- 【使用Python实现算法】04 标准库(数据类型模块)
- python-协程并发-多任务协程的实现方式(一)
- python-Python与MongoDB数据库-使用Python执行MongoDB查询(一)
- 网络工程师学Python-25-文件处理
- python中os模块的常用方法详解编程语言
- python通过ssh-powershell监控windows详解编程语言
- python播放wav音频文件代码详解编程语言
- Python实现HTTP代理服务器详解编程语言
- 如何编写Python软件开发文档(7个技巧)
- Python结合MySQL实现信息交互(python与mysql交互)
- Python实现快速连接Redis数据库(python连接redis)
- python从MSSQL到Python:一段跨语言的旅程(mssql除以)
- Linux下Python编程:从入门到精通(linux下python编程)
- 使用cxoracle模块,开发Python与Oracle数据库的连接(cx_oracle模块)
- 用Python实现QQ游戏大家来找茬辅助工具