【问题标题】:Can we shed some definitive light on how python packaging and import works?我们能否明确说明 python 打包和导入的工作原理?
【发布时间】:2011-08-08 13:34:39
【问题描述】:

我有机会通过 python 管理模块,每次都是一个挑战:打包不是人们每天都在做的事情,它成为学习的负担,成为记忆的负担,即使你实际去做,因为这通常会发生一次。

我想在这里收集有关导入、包管理和分发如何在 python 中工作的权威概述,以便这个问题成为对引擎盖下发生的所有魔法的权威解释。虽然我理解这个问题的广泛层面,但这些事情是如此交织在一起,以至于任何有针对性的答案都无法解决主要问题:了解所有工作原理,什么是过时的,什么是最新的,什么是同一任务的替代品,什么是怪癖。

要参考的关键字列表如下,但这只是其中的一个示例。还有更多,欢迎您添加更多详细信息。

  • PyPI
  • setuptools / 分发
  • distutils
  • 鸡蛋
  • 鸡蛋链接
  • 压缩导入
  • site.py
  • 网站包
  • .pth 文件
  • 虚拟环境
  • 在 Egg 中处理已编译模块(通过 easy_install 安装和不安装)
  • get_data() 的使用
  • pypm
  • bento
  • PEP 376
  • 奶酪店
  • 鸡蛋安全

链接到其他答案可能是个好主意。正如我所说,这个问题是针对高级概述的。

【问题讨论】:

  • @Lott :它只解释了 distutils,而且太长了。我想要这里的短篇小说。
  • @Lott :问题:它们怎么可能“不是非常密切相关”,但您提出了单个链接作为解决方案?
  • @AJ:我不完全同意。过多的竞争会导致解决方案欠佳、人力浪费和普遍的挫败感。更重要的是:forthescience.org/blog/2009/09/17/…
  • @Stefano,我可以建议您以您自己的关于其中一个特定体验的答案来启动程序。例如distutils!

标签: python packaging


【解决方案1】:

在很大程度上,这是对包装/分发方面的尝试,而不是import 的机制。不幸的是,打包是 Python 提供不止一种方法的地方。我只是想让球滚动,希望其他人能帮助填补我的遗漏或指出错误。

首先这里有一些混乱的术语。包含__init__.py 文件的目录是一个包。但是,我们在这里讨论的大部分内容是在 PyPI、其中一个镜像或供应商特定的包管理系统(如 Debian 的 Apt、Redhat 的 Yum、Fink、Macports、Homebrew 或 ActiveState 的 pypm)上发布的特定版本的包。

这些已发布的包是人们试图将其称为“发行版”的东西,试图将“包”仅用作 Python 语言结构。您可以在PEP-376PEP-376 中看到其中的一些用法。

现在,您的关键字列表与 Python 生态系统的几个不同方面有关:

查找和发布 python 发行版:

  • PyPI(又名奶酪店)
  • PyPI 镜像
  • 各种包管理工具/系统:apt、yum、fink、macports、homebrew
  • pypm(ActiveState 的 PyPI 替代品)

以上都是提供以各种格式发布 Python 发行版的场所的所有服务。有些,例如 PyPI 镜像和 apt / yum 存储库,可以在您的本地计算机或您的公司网络中运行,但人们通常使用官方的。大多数(如果不是全部)都提供了一个工具(或 PyPI 中的多个工具)来帮助查找和下载发行版。

用于创建和安装发行版的库:

  • setuptools/分发
  • distutils

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 将作为 Distutil 的 from distutils.core import setup 的继任者被包含在 Python 3 中。

Setuptools 和 Distribute 都提供了自定义版本的 distutils setup 命令 做一些有用的事情,比如支持 Egg 格式。

Python 分发格式:

发行版通常以源档案(tarball 或 zipfile)的形式提供。安装源代码分发的标准方法是下载并解压缩存档,然后运行其中的 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 的 Jarfiles,它们有很多你应该阅读的特性 here

Python 包格式:

  • 未压缩的目录
  • zipimport(zip 压缩目录)

一个普通的python包只是一个包含__init__.py文件和任意数量的附加模块或子包的目录。 Python 还支持在 *.zip 文件中查找和加载源代码,只要它们包含在 PYTHONPATH (sys.path) 中即可。

安装 Python 包:

  • easy_install:原版egg安装工具,依赖setuptools
  • pip:目前最流行的安装python包的方式。类似于easy_install,但更灵活,并且具有一些不错的功能,例如需求文件,以帮助记录依赖关系和重现部署。
  • pypmaptyum、fink 等

环境管理/自动化部署:

  • bento
  • buildout
  • virtualenv(和virtualenvwrapper

上述工具用于帮助自动化和管理 Python 项目的依赖项。基本上,它们为您提供工具来描述您的应用程序需要哪些发行版,并自动安装这些特定版本的依赖项。

软件包/发行版的位置:

  • 网站包
  • PYTHONPATH
  • 当前工作目录(取决于您的操作系统和环境设置)

默认情况下,安装 python 发行版会将其放入 site-packages 目录。该目录通常类似于/usr/lib/pythonX.Y/site-packages

一种查找站点包目录的简单编程方式:

from distuils import sysconfig
print sysconfig.get_python_lib()

修改 PYTHONPATH 的方法:

Python 的 import 语句只会查找位于您的 PYTHONPATH 中包含的目录之一中的包。

您可以通过以下方式在 Python 中检查和更改您的路径:

import sys
print sys.path
sys.path.append("/home/myname/lib")

除此之外,您可以像设置操作系统上的任何其他环境变量一样设置PYTHONPATH 环境变量,或者您可以使用:

  • .pth 文件:读取位于您的PYTHONPATH 上的目录中的 *.pth 文件,并将 *.pth 文件的每一行添加到您的PYTHONPATH。基本上,只要您将包复制到PYTHONPATH 上的目录中,您就可以改为创建mypackages.pth。阅读有关 *.pth 文件的更多信息:site module
  • egg-link 文件:Internal structure of python eggs 它们是符号链接的跨平台替代品。创建 egg 链接文件类似于创建 pth 文件。
  • site.py修改

要将上述/home/myname/lib 添加到带有*.pth 文件的站点包中,您需要创建一个*.pth 文件。文件名无关紧要,但您仍然应该选择合理的名称。

让我们创建myname.pth:

# myname.pth
/home/myname/lib

就是这样。将其放入系统上的sysconfig.get_python_lib()PYTHONPATH 中的任何其他目录中,/home/myname/lib 将被添加到路径中。

【讨论】:

  • Python3.3 添加了packaging 模块(在Python pip install distutils2 使用)
【解决方案2】:

对于包装问题,这应该有助于http://guide.python-distribute.org/

对于导入,Fredrik Lundh http://effbot.org/zone/import-confusion.htm 的旧文章仍然是一个很好的起点。

【讨论】:

    【解决方案3】:

    我推荐Tarek Ziadek's Book on Python. 有一章专门讲打包和分发。

    【讨论】:

      【解决方案4】:

      我认为不需要探索 import(Python 的命名空间和导入功能很直观,恕我直言)。

      我现在只使用pip。我没有遇到任何问题。

      不过,包装和分销这个话题是值得探讨的。我不会给出冗长的答案,而是这样说:

      我通过简单地复制 Pylons 或许多其他开源包的做法,学会了如何打包和分发我自己的“包”。然后,我将这种模板与阅读文档结合起来,进一步充实它,并提出了一种可靠的分发方法。

      当您了解 python(distutils 和 pypi)的包管理和分发时,它实际上非常强大。我很喜欢。

      [编辑]

      我还想补充一点关于 virtualenv 的内容。用它。我为每个项目创建一个 virtualenv,我总是使用--no-site-packages;我在 virtualev 中安装了该特定项目所需的所有软件包(即使它们是共同的,例如lxml)。它使所有内容保持隔离,并且我更容易在脑海中维护分组(而不是试图跟踪 python 的位置和版本!)

      [/编辑]

      【讨论】:

      • I don't think import needs to be explored。我不同意。在导入 zip 文件、导入命名空间包、导入 egg、pth 文件等方面,有很多“黑魔法”(如果你不知道事件链的话)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-07
      • 2016-02-19
      • 2013-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-15
      相关资源
      最近更新 更多