最小的结构

让我们来看一小段代码:

def joke():
    return (u'How do you tell HTML from HTML5?'
            u'Try it out in Internet Explorer.'
            u'Does it work?'
            u'No?'
            u'It\'s HTML5.')

这小段代码仅仅是为了展示如何打包和分发Python代码, 没有实际的用途。

选择一个包名

Python 模块或者包名应该遵守以下的规则:

  • 全小写
  • 不要和pypi上已有的包名重复,即使你不想公开发布你的包,因为你的包可能作为其他包的依赖包
  • 使用下划线分隔单词或者什么都不用(不要使用连字符)

现在把我们的函数变成一个Python module funniest

开始工作

目录结构 funniest 如下:

funniest/
    funniest/
        __init__.py
    setup.py

最外层的目录是我们版本管理工具的根目录, 例如 funniest.git . 子目录也叫 funniest , 代表Python module.

为了更好理解, 我们把函数 joke() 放到 __init__.py 中:

def joke():
    return (u'How do you tell HTML from HTML5?'
            u'Try it out in Internet Explorer.'
            u'Does it work?'
            u'No?'
            u'It\'s HTML5.')

最主要的setup配置文件是 setup.py , 应该包含一行代码调用 setuptools.setup() ,就像下面这样:

from setuptools import setup

setup(name='funniest',
      version='0.1',
      description='The funniest joke in the world',
      url='http://github.com/storborg/funniest',
      author='Flying Circus',
      author_email='flyingcircus@example.com',
      license='MIT',
      packages=['funniest'],
      zip_safe=False)

现在我们可以在本地安装这个python包:

$ python setup.py install

我们也可以使用开发模式安装这个包, 每次修改代码之后不用重新安装, 立即可用最新的代码.:

$ python setup.py develop

不管用哪种方式,安装之后就可以在python中使用这个包:

>>> import funniest
>>> print funniest.joke()

在PyPI上发布

脚本 setup.py 也是在PyPI注册和上传源码包的入口.

第一步注册这个包(包括注册包名,上传元数据,创建pypi.python.org的页面):

$ python setup.py register

如果从未在PyPI上发布过东西, 你需要创建一个账号, 命令行向导会一步一步告诉你怎么做.

注册之后你可以在PyPI看到这个包的页面 funniest :

http://pypi.python.org/pypi/funniest/0.1

尽管用户可以根据URL链接找到你的git仓库, 但是为了使用方便我们需要上传一个源码包. 用户不需要clone你的git仓库,而且可以使用安装工具 自动化安装和搜索依赖关系.

第二步创建一个源码包:

$ python setup.py sdist

这一步会在你的顶层目录下创建 dist/funniest-0.1.tar.gz . 如果你有时间, 可以把这个文件拷贝到另一台主机上, 解压然后安装, 测试一下安装包.

第三步上传到PyPI:

$ python setup.py sdist upload

你可以把这几步结合起来, 更新元数据, 发布新版本, 一步就完成:

$ python setup.py register sdist upload

想要查看setup.py更多的功能可以看看帮助:

$ python setup.py --help-commands

安装这个包

上面的步骤完成之后, 其他用户可以直接用 easy_install 安装:

easy_install funniest

或者使用 pip

$ pip install funniest

如果这包作为其他包的依赖包, 它将被自动安装(我们在后面会提到如何配置)

添加其他文件

大部分时间我们的代码分散在多个文件当中,

举个例子, 我们把函数移动到一个新的文件中 text , 现在我们的目录结构是这样子的:

funniest/
    funniest/
        __init__.py
        text.py
    setup.py

__init__.py

from .text import joke

text.py

def joke():
    return (u'How do you tell HTML from HTML5?'
            u'Try it out in Internet Explorer.'
            u'Does it work?'
            u'No?'
            u'It\'s HTML5.')

所有的代码应该都在 funniest/funniest/ 目录下.

忽略的文件 (.gitignore, etc)

我们可能需要一个 .gitignore 或者是其他代码管理工具类似的文件, 因为创建包的过程中会产生一下中间文件, 我们并不想提交到代码仓库当中.

下面是一个 .gitignore 的例子:

# Compiled python modules.
*.pyc

# Setuptools distribution folder.
/dist/

# Python egg metadata, regenerated from source files by setuptools.
/*.egg-info

大功告成

上面讲的结构已经包含了创建一个包的所有步骤. 如果所有的Python工具和库都遵循同样的规则来打包, 世界会更加美好.

客官别急 下面还有更多内容, 因为大部分的包还需要命令行脚本, 文档, 测试,分析工具等等, 请看下一篇.