解析Python编程中的包结构


Posted in Python onOctober 25, 2015

假设你想设计一个模块集(也就是一个“包”)来统一处理声音文件和声音数据。通常由它们的扩展有不同的声音格式,例如:WAV,AIFF,AU),所以你可能需要创建和维护一个不断增长的各种文件格式之间的转换的模块集合。并且可能要执行声音数据处理(如混合,添加回声,应用平衡功能),所以你写一个永无止境的流模块来执行这些操作:模块设计的包如下:

sound/             Top-level package
   __init__.py        Initialize the sound package
   formats/         Subpackage for file format conversions
       __init__.py
       wavread.py
       wavwrite.py
       aiffread.py
       aiffwrite.py
       auread.py
       auwrite.py
       ...
   effects/         Subpackage for sound effects
       __init__.py
       echo.py
       surround.py
       reverse.py
       ...
   filters/         Subpackage for filters
       __init__.py
       equalizer.py
       vocoder.py
       karaoke.py
       ...

当导入包以后,Python通过sys.path中的目录来寻找包的子目录。 每一个包都必须有__init__.py文件,这样做是为了防止某些目录有一个共同的名字。在最简单的情况下,__ init__.py可以只是一个空文件,但它也可以执行包的初始化代码,包括设置__all__变量,稍后介绍。 我们可以从包中导入单个模块,

例如: import sound.effects.echo 这会载入子模块sound.effects.echo。它必须引用全名。

sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

另外一种导入子模块的方法: from sound.effects import echo 这样就加载了echo子模块,没有包括包的前缀,因此它可以用作如下:

echo.echofilter(input, output, delay=0.7, atten=4)

或者可以

from sound.effects.echo import echofilter echofilter(input, output, delay=0.7, atten=4)

请注意,如果你使用包导入一个子模块(或子包),像一个函数,类或变量。 import语句首先测试导入的对象是否包中定义,如果没有,它假定这是一个模块,并尝试加载它。如果还没有找到,则会引发一个ImportError异常。

python 包管理工具大乱斗
1. distutils

distutils 是 python 标准库的一部分,2000年发布。使用它能够进行 python 模块的 安装 和 发布。

setup.py 就是利用 distutils 的功能写成,我们可以看一个简单的 setup.py 的例子。

在这里可以看到关于 setupt.py 格式的所有详细描述:Writing the Setup Script。

要安装一个模块到当前的 python 环境中,可以使用这个模块提供的 setup.py 文件:

python setup.py install
下面的代码会发布一个 python 模块,将其打包成 tar.gz 或者 zip 压缩包:
python setup.py sdist

甚至能打包成 rpm 或者 exe 安装包:

python setup.py bdist_rpm
python setup.py bdist_wininst

2. setuptools 和 distribute

setuptools 是一个为了增强 distutils 而开发的集合,2004年发布。它包含了 easy_install 这个工具。

ez_setup.py 是 setuptools 的安装工具。ez 就是 easy 的缩写。

简单的说,setuptools 是一个项目的名称,是基础组件。而 easy_install 是这个项目中提供的工具,它依赖基础组件工作。

为了方便描述,下面文章中提到的 setuptools 被认为与 easy_install 同义。

使用 setuptools 可以自动 下载、构建、安装和管理 python 模块。

例如,从 PyPI 上安装一个包:

easy_install SQLObject

下载一个包文件,然后安装它:

easy_install http://example.com/path/to/MyPackage-1.2.3.tgz

从一个 .egg 格式安装:

easy_install /my_downloads/OtherPackage-3.2.1-py2.3.egg

distribute 是 setuptools 的一个分支版本。分支的原因可能是有一部分开发者认为 setuptools 开发太慢了。但现在,distribute 又合并回了 setuptools 中。因此,我们可以认为它们是同一个东西。事实上,如果你查看一下 easy_install 的版本,会发现它本质上就是 distribute 。

# easy_install --version
distribute 0.6.28

3. Eggs

Eggs 格式是 setuptools 引入的一种文件格式,它使用 .egg 扩展名,用于 Python 模块的安装。

setuptools 可以识别这种格式。并解析它,安装它。

4. pip

注意,从此处开始,easy_install 和 setuptools 不再同义。

pip 是目前 python 包管理的事实标准,2008年发布。它被用作 easy_install 的替代品,但是它仍有大量的功能建立在 setuptools 组件之上。

pip 希望不再使用 Eggs 格式(虽然它支持 Eggs),而更希望采用“源码发行版”(使用 python setup.py sdict 创建)。这可以充分利用 Requirements File Format 提供的方便功能。

pip 可以利用 requirments.txt 来实现在依赖的安装。在 setup.py 中,也存在一个 install_requires 表来指定依赖的安装。

pip 支持 git/svn/hg 等流行的 VCS 系统,可以直接从 gz 或者 zip 压缩包安装,支持搜索包,以及指定服务器安装等等功能。

pip vs easy_install 详细介绍了两者的不同。它们可以说是各占胜场,但 pip 明显优势更大。

5. wheel

wheel 本质上是一个 zip 包格式,它使用 .whl 扩展名,用于 python 模块的安装,它的出现是为了替代 Eggs。

wheel 还提供了一个 bdist_wheel 作为 setuptools 的扩展命令,这个命令可以用来生成 wheel 包。

pip 提供了一个 wheel 子命令来安装 wheel 包。当然,需要先安装 wheel 模块。

setup.cfg 可以用来定义 wheel 打包时候的相关信息。

Wheel vs Egg 详细介绍了 wheel 和 Eggs 格式的区别,很显然,wheel 优势明显。

Python Wheels 网站展示了使用 Wheels 发行的 python 模块在 PyPI 上的占有率。

pypip.in 也支持 wheel。

6. distutils2 和 distlib

distutils2 被设计为 distutils 的替代品。从2009年开发到2012年。它包含更多的功能,并希望以 packaging 作为名称进入 python 3.3 成为标准库的一部分。但这个计划 后来停滞了 。

distlib 是 distutils2 的部分,它为 distutils2/packaging 提供的低级功能增加高级 API,使其便于使用。

这里 介绍了 distlib 没有进入 python 3.3 标准库的一些原因。

因此,可以暂时不必了解这两个工具,静观其变即可。

Python 相关文章推荐
Python中尝试多线程编程的一个简明例子
Apr 07 Python
Python爬虫利用cookie实现模拟登陆实例详解
Jan 12 Python
Python 安装setuptools和pip工具操作方法(必看)
May 22 Python
基于python3 类的属性、方法、封装、继承实例讲解
Sep 19 Python
python matplotlib 注释文本箭头简单代码示例
Jan 08 Python
VSCode下配置python调试运行环境的方法
Apr 06 Python
python3 requests中使用ip代理池随机生成ip的实例
May 07 Python
利用Python如何将数据写到CSV文件中
Jun 05 Python
Python设计模式之组合模式原理与用法实例分析
Jan 11 Python
基于腾讯云服务器部署微信小程序后台服务(Python+Django)
May 08 Python
python数据预处理方式 :数据降维
Feb 24 Python
python GUI库图形界面开发之PyQt5选项卡控件QTabWidget详细使用方法与实例
Mar 01 Python
Python实现获取域名所用服务器的真实IP
Oct 25 #Python
Python制作爬虫采集小说
Oct 25 #Python
Python验证企业工商注册码
Oct 25 #Python
日常整理python执行系统命令的常见方法(全)
Oct 22 #Python
Python六大开源框架对比
Oct 19 #Python
Python脚本暴力破解栅栏密码
Oct 19 #Python
python学习笔记之调用eval函数出现invalid syntax错误问题
Oct 18 #Python
You might like
合作指挥官:孟斯克
2020/03/16 星际争霸
用PHP调用数据库的存贮过程!
2006/10/09 PHP
php mssql扩展SQL查询中文字段名解决方法
2012/10/15 PHP
Android App中DrawerLayout抽屉效果的菜单编写实例
2016/03/21 PHP
如何用PHP做到页面注册审核
2017/03/02 PHP
利用PHPStorm如何开发Laravel应用详解
2017/08/30 PHP
利用PHP访问MySql数据库的逻辑操作以及增删改查的实例讲解
2017/08/30 PHP
详解PHP 二维数组排序保持键名不变
2019/03/06 PHP
Javascript Object.extend
2010/05/18 Javascript
Javascript new Date().valueOf()的作用与时间戳由来详解
2013/04/24 Javascript
js截取固定长度的中英文字符的简单实例
2013/11/22 Javascript
在JavaScript中用getMinutes()方法返回指定的分时刻
2015/06/10 Javascript
深入讲解AngularJS中的自定义指令的使用
2015/06/18 Javascript
使用 stylelint检查CSS_StyleLint
2016/04/28 Javascript
AngularJS ng-template寄宿方式用法分析
2016/11/07 Javascript
彻底学会Angular.js中的transclusion
2017/03/12 Javascript
JavaScript定义函数_动力节点Java学院整理
2017/06/27 Javascript
基于dataset的使用和图片延时加载的实现方法
2017/12/11 Javascript
angularJs自定义过滤器实现手机号信息隐藏的方法
2018/10/08 Javascript
React如何解决fetch跨域请求时session失效问题
2018/11/02 Javascript
详解如何使用微信小程序云函数发送短信验证码
2019/03/13 Javascript
详解vue父子组件关于模态框状态的绑定方案
2019/06/05 Javascript
在Python中处理字符串之ljust()方法的使用简介
2015/05/19 Python
python爬虫入门教程--HTML文本的解析库BeautifulSoup(四)
2017/05/25 Python
TF-IDF算法解析与Python实现方法详解
2017/11/16 Python
Python用for循环实现九九乘法表
2018/05/31 Python
用 Python 制作地球仪的方法
2020/04/24 Python
美国最大网上鞋店:Zappos
2016/07/25 全球购物
iHerb俄罗斯:维生素、补品和天然产品
2020/07/09 全球购物
音乐教学随笔感言
2014/02/19 职场文书
厉行勤俭节约倡议书
2014/05/16 职场文书
商业门面租房协议书
2014/11/25 职场文书
防溺水安全教育主题班会
2015/08/12 职场文书
HTML基础-标签分类(闭合标签,空标签,块级元素,行内元素,行级块元素,可替换元素)
2021/03/31 HTML / CSS
pytorch中[..., 0]的用法说明
2021/05/20 Python
navicat 连接Ubuntu虚拟机的mysql的操作方法
2022/04/02 MySQL