我们能否明确解释Python打包和导入的工作原理?
我在学习Python模块管理的过程中遇到了不少挑战。打包并不是人们每天都在做的事情,所以学习起来很麻烦,记起来也很费劲,尤其是你可能只在某个特定的时刻才会用到它。
我想在这里整理一个关于Python中导入、包管理和分发的全面概述,这样这个问题就能成为所有背后运作的魔法的最终解释。虽然我理解这个问题的大致方向,但这些内容是紧密相连的,任何单一的回答都无法解决主要问题:理解这一切是如何运作的,哪些是过时的,哪些是当前的,哪些只是完成同一任务的替代方案,还有哪些是特别之处。
以下是一些关键词供参考,但这只是其中的一部分。还有很多其他内容,欢迎大家补充更多细节。
- PyPI
- setuptools / Distribute
- distutils
- eggs
- egg-link
- pip
- zipimport
- site.py
- site-packages
- .pth文件
- virtualenv
- 处理在egg中的编译模块(使用和不使用easy_install安装)
- 使用get_data()
- pypm
- bento
- PEP 376
- 奶酪商店
- eggsecutable
链接到其他答案可能是个好主意。正如我所说,这个问题是为了提供一个高层次的概述。
4 个回答
我推荐一本关于Python的书,作者是Tarek Ziadek,你可以在这里找到。书里有一章专门讲如何打包和分发你的代码。
关于打包的问题,这里有个链接可以帮助你:http://guide.python-distribute.org/
至于导入模块,Fredrik Lundh 的一篇旧文章http://effbot.org/zone/import-confusion.htm依然是个很好的入门参考。
大体上,这段内容是想讨论Python的打包和分发方面,而不是具体的import
机制。不幸的是,Python在打包方面提供了很多种方法,这让人有点困惑。我只是想先抛砖引玉,希望其他人能补充我遗漏的部分或指出我的错误。
首先,这里有一些术语比较混乱。包含__init__.py
文件的目录被称为包。不过,我们这里讨论的主要是发布在PyPI(Python包索引)及其镜像网站上的特定版本的包,或者是在像Debian的Apt、Redhat的Yum、Fink、Macports、Homebrew或ActiveState的pypm这样的特定包管理系统中的包。
这些发布的包通常被称为“分发”,目的是将“包”这个词仅限于Python语言的构造。你可以在PEP-376中看到一些这样的用法。
接下来,你提到的关键词涉及Python生态系统的几个不同方面:
查找和发布Python分发:
- PyPI(也叫奶酪商店)
- PyPI镜像
- 各种包管理工具/系统:apt、yum、fink、macports、homebrew
- pypm(ActiveState的PyPI替代品)
以上这些都是提供发布Python分发的服务,格式各异。有些,比如PyPI镜像和apt/yum仓库,可以在你的本地机器或公司网络中运行,但人们通常使用官方的。大多数情况下,它们提供工具(在PyPI的情况下有多个工具)来帮助查找和下载分发。
用于创建和安装分发的库:
setuptools
/ Distributedistutils
Distutils是Python包编译和构建成分发的标准基础设施。distutils
有很多功能,但大多数人只知道:
from distutils.core import setup
setup(name='Distutils',
version='1.0',
description='Python Distribution Utilities',
author='Greg Ward',
author_email='gward@python.net',
url='http://www.python.org/sigs/distutils-sig/',
packages=['distutils', 'distutils.command'],
)
在某种程度上,这就是你所需要的大部分内容。通过前面9行代码,你就有足够的信息来安装一个纯Python包,并且拥有发布该包到PyPI所需的最少元数据。
Setuptools提供了支持Egg格式及其所有特性的必要钩子。Distribute是Setuptools的一个替代品,增加了一些功能,同时尽量保持向后兼容。我相信Distribute将作为Distutils的继任者包含在Python 3中,替代from distutils.core import setup
。
Setuptools和Distribute都提供了distutils
的自定义版本的设置命令,能够做一些有用的事情,比如支持Egg格式。
Python分发格式:
- 源代码
- Eggs
分发通常以源代码归档(tarball或zip文件)的形式提供。安装源分发的标准方法是下载并解压归档文件,然后运行里面的setup.py
文件。
例如,以下命令将下载、构建并安装Pygments语法高亮库:
curl -O -G http://pypi.python.org/packages/source/P/Pygments/Pygments-1.4.tar.gz
tar -zxvf Pygments-1.4.tar.gz
cd Pygments-1.4
python setup.py build
sudo python setup.py install
另外,你也可以下载Egg文件并安装。通常通过使用easy_install或pip来完成:
sudo easy_install pygments
or
sudo pip install pygments
Eggs的灵感来源于Java的Jar文件,它们有很多特性,你可以在这里了解更多。
Python包格式:
- 未压缩的目录
- zipimport(压缩的目录)
一个普通的Python包就是一个包含__init__.py
文件的目录,里面可以有任意数量的额外模块或子包。Python还支持在*.zip文件中查找和加载源代码,只要这些文件被包含在PYTHONPATH
(sys.path
)中。
安装Python包:
easy_install
:最初的Egg安装工具,依赖于setuptools
pip
:目前最流行的安装Python包的方法。类似于easy_install
,但更灵活,具有一些很好的功能,比如需求文件,帮助记录依赖关系和重现部署。pypm
、apt
、yum
、fink等
环境管理/自动化部署:
bento
buildout
virtualenv
(和virtualenvwrapper
)
以上工具用于帮助自动化和管理Python项目的依赖关系。基本上,它们提供工具来描述你的应用程序所需的分发,并自动安装这些特定版本的依赖。
包/分发的位置:
- site-packages
PYTHONPATH
- 当前工作目录(取决于你的操作系统和环境设置)
默认情况下,安装Python分发会将其放入site-packages目录。这个目录通常是/usr/lib/pythonX.Y/site-packages
。
找到你的site-packages目录的简单编程方法:
from distuils import sysconfig
print sysconfig.get_python_lib()
修改PYTHONPATH的方法:
Python的import语句只会找到位于PYTHONPATH
中包含的目录的包。
你可以通过访问以下内容来检查和更改你的路径:
import sys
print sys.path
sys.path.append("/home/myname/lib")
除此之外,你可以像设置其他环境变量一样设置PYTHONPATH
环境变量,或者你可以使用:
- .pth文件:位于已经在
PYTHONPATH
中的目录中的*.pth文件会被读取,每一行都会被添加到你的PYTHONPATH
中。基本上,每次你想把一个包复制到PYTHONPATH
中的某个目录时,你可以创建一个mypackages.pth
文件。关于*.pth文件的更多信息,请查看site模块 - egg-link文件:Python eggs的内部结构,它们是符号链接的跨平台替代品。创建一个egg链接文件类似于创建一个pth文件。
site.py
的修改
要将/home/myname/lib
添加到site-packages,你可以创建一个*.pth文件。文件名无所谓,但最好选择一个合理的名字。
让我们创建一个myname.pth
:
# myname.pth
/home/myname/lib
就这样。把这个文件放到sysconfig.get_python_lib()
所在的目录或你的PYTHONPATH
中的任何其他目录中,/home/myname/lib
就会被添加到路径中。