zoukankan      html  css  js  c++  java
  • 怎样制作一个 Python Egg

    from:http://liluo.org/blog/2012/08/how-to-create-python-egg/

    制作打包一个 Python Egg 并部署整个过程还蛮有意思的,下面小教程(这里以制作一个叫作 bee 的 Egg 为例)~

    制作

    先创建一个项目文件夹:

    1
    2
    
    $ mkdir bee-egg # 这个名字可以随便取
    $ cd bee-egg
    

    在里边建一个叫 bee 的文件夹(逻辑比较简单的话可以直接建一个叫作 bee.py 的文件),放业务逻辑代码:

    1
    2
    
    mkdir bee
    touch bee/__init__.py
    

    其中 bee/init.py 写几行代码:

    1
    2
    3
    4
    5
    6
    7
    
    # -*- coding: utf-8 -*-
    
    def hoot():
        return 'hum hum'
    
    def add(x, y):
        return x + y
    

    在 bee-egg 目录中创建 Egg 的配置文件 setup.py :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    #!/usr/bin/env python
    
    from setuptools import setup, find_packages
    
    setup(
        name = 'bee',
        version = '0.0.1',
        keywords = ('bee', 'egg'),
        description = 'a simple egg',
        license = 'MIT License',
    
        url = 'http://liluo.org',
        author = 'liluo',
        author_email = 'i@liluo.org',
    
        packages = find_packages(),
        include_package_data = True,
        platforms = 'any',
        install_requires = [],
    )
    

    *setup 中完整的参数及说明可以看 http://docs.python.org/distutils/setupscript.html#additional-meta-data

    当前目录文件结构如下:

    1
    2
    3
    4
    
    bee-egg/
            bee/
               __init__.py
            setup.py
    

    打包

    打包是最重要却又最简单的一步,执行:

    1
    
    python setup.py xxxx
    

    即可。比较主流的2种打包格式:

    1
    2
    3
    
    # 以下所有生成文件将在当前路径下 dist 目录中
    python setup.py bdist_egg # 生成类似 bee-0.0.1-py2.7.egg,支持 easy_install 
    python setup.py sdist     # 生成类似 bee-0.0.1.tar.gz,支持 pip 
    

    当然还有其他非主流格式或者其他选项,可以通过下面这个命令查看:

    1
    
    python setup.py --help-commands
    

    部署到 PyPI

    注册 Egg

    可以通过 SSH 或者 web form ,SSH 步骤:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    $ python setup.py register
    running register
    running egg_info
    writing bee.egg-info/PKG-INFO
    writing top-level names to bee.egg-info/top_level.txt
    writing dependency_links to bee.egg-info/dependency_links.txt
    reading manifest file 'bee.egg-info/SOURCES.txt'
    writing manifest file 'bee.egg-info/SOURCES.txt'
    running check
    We need to know who you are, so please choose either:
     1. use your existing login,
     2. register as a new user,
     3. have the server generate a new password for you (and email it to you), or
     4. quit
    Your selection [default 1]:
    
    Username: liluo
    Password:
    Registering bee to http://pypi.python.org/pypi
    Server response (200): OK
    I can store your PyPI login so future submissions will be faster.
    (the login will be stored in /Users/luo/.pypirc)
    Save your login (y/N)?y
    

    *关于 register 更详细的内容可以看 http://docs.python.org/distutils/packageindex.html

    上传到 PyPI

    上传文件也是有 SSH 和 web form 2种方法。

    web form: 在浏览器登陆到 PyPI 点击 Your packages 中 Egg 的项目,然后选择某个版本的 files 即可看到上传界面。

    SSH:

    1
    2
    3
    4
    5
    6
    7
    8
    
    $ python setup.py sdist bdist_egg upload
    # 这里上传的是 .tar.gz 压缩包和 .egg 文件
    # 屏幕上大片信息输出,最后会看到
    running upload
    Submitting dist/bee-0.0.1.tar.gz to http://pypi.python.org/pypi
    Server response (200): OK
    Submitting dist/bee-0.0.1-py2.7.egg to http://pypi.python.org/pypi
    Server response (200): OK
    

    安装测试

    先用 pip 安装:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    $ pip install bee
    Downloading/unpacking bee
      Downloading bee-0.0.1.tar.gz
      Running setup.py egg_info for package bee
    
    Installing collected packages: bee
      Running setup.py install for bee
    
    Successfully installed bee
    Cleaning up...
    

    测试:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    $ python
    >>> import bee
    >>> dir(bee)
    ['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'add', 'hoot']
    >>> bee.add(1,3)
    4
    >>> from bee import hoot
    >>> hoot()
    'hum hum'
    

    Yeah!现在世界人民都可以用 [bee]http://pypi.python.org/pypi/bee/ 这个 Python Egg 了~

    卸载掉用 easy_install 试下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    $ pip uninstall bee
    Uninstalling bee:
      /Library/Python/2.7/site-packages/bee
      /Library/Python/2.7/site-packages/bee-0.0.1-py2.7.egg-info
    Proceed (y/n)? y
      Successfully uninstalled bee
    $ easy_install bee
    Searching for bee
    Reading http://pypi.python.org/simple/bee/
    Reading http://liluo.org
    Best match: bee 0.0.1
    Downloading http://pypi.python.org/packages/2.7/b/bee/bee-0.0.1-py2.7.egg#md5=6b5a719f1ca42367fb05d1e3eb45fbe5
    Processing bee-0.0.1-py2.7.egg
    Moving bee-0.0.1-py2.7.egg to /Library/Python/2.7/site-packages
    Adding bee 0.0.1 to easy-install.pth file
    
    Installed /Library/Python/2.7/site-packages/bee-0.0.1-py2.7.egg
    Processing dependencies for bee
    Finished processing dependencies for bee
    

    可以再重做一下上面的测试,验证一下。

    *关于 upload 更详细的内容可以看 http://docs.python.org/distutils/uploading.html

    Tips

    pip install xxxx 时默认只会找对应的压缩包文件

    当时我用 easy_install 安装没问题,但是 pip 每次都说找不到资源。我盯着 @hongqn 在 PyPI 上的 CaoE 足足2分钟才反应过来,原来它是需要一个压缩包格式的文件。

    setup.py 中调用当前目录的文件一定要加 MANIFEST.in 并将调用文件 include 进来

    使用 python setup.py sdist 打包时,如果 setup.py 调用了当前目录中的文件(如README.rst):

    1
    
    long_description = open('README.rst').read()
    

    一定要在增加 MANIFEST.in 文件并将调用文件 include 进来,否则将导致用户在 pip install 时报文件找不到的错误,示例:

    1
    2
    
    $ cat MANIFEST.in
    include README.rst
    

    更详情的可以看 http://docs.python.org/distutils/sourcedist.html#specifying-the-files-to-distribute

    偶尔去看一下自己的 Egg 在 PyPI 上的下载数也挺欢乐的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    Version: 0.0.3
    py-oauth2-0.0.3.tar.gz(251)
    py_oauth2-0.0.3-py2.7.egg(218)
    
    Version: 0.0.2
    py-oauth2-0.0.2.tar.gz(376)
    py_oauth2-0.0.2-py2.6.egg(435)
    py_oauth2-0.0.2-py2.7.egg(304)
    
    Version: 0.0.1
    py_oauth2-0.0.1-py2.6.egg(478)
    

    END

     

     

    首先一个问题是“Python的package是如何定义的?”这个似乎是面试Python程序员最常出现的题目。简而言之,在目录下放置一个__init__.py文件,这个目录就会成为一个package。

    首先是制作一个干净的目录用于打包,本例中就简单粗暴的定义为~/project目录,要打包的package就命名为spawn-egg(注:这里只是用来Demo的名字,命名方式并不适合所有的python环境)。目录结构如下:

    ilab@iLab-Dev:~/project$ find ./
    ./
    ./spawn-egg
    ./spawn-egg/Base.pyc
    ./spawn-egg/hello.py
    ./spawn-egg/Base.py
    ./spawn-egg/__init__.py

    然后就是制作一个setup.py脚本,与其说是脚本,这个文件更像是一个配置文件。

    vi ~/project/setup.py

    from setuptools import setup, find_packages
    
    setup(
     name = "spawn-egg",
     version="0.1.0",
     packages = find_packages(),
     description = "test how to make eggs",
     author = "Litrin J.",
     author_email = "XXX@gmail.com",
    
     license = "GPL",
     keywords = ("test", "python"),
     platforms = "Independant",
     url = "",
     )

    就是一个setup函数,入参真心不少,好在字面上很容易理解它的用途,总结起来就这几个比较常用:

    • name:就是名字了
    • version:版本号
    • packages:包含的package,setuptools自带了一个find_packages()工具可以自动从name同名的folder下找到package。
    • description:对于这个包的描述,如果描述内容很长,可以把这里当成摘要,更详细的内容使用long_description参数
    • author/author_email:作者和邮箱
    • keywords:关键字,便于发布到pip上,用于搜索。

    更详细的解释请见

    准备打包环境。打包环境需要setuptools,对于Ubuntu用户来说,直接

    apt-get install python-setuptools

    生成egg,激动人心的时刻来了!

    ilab@iLab-Dev:~/project$ python setup.py bdist_egg
    running bdist_egg
    running egg_info
    creating spawn_egg.egg-info
    writing spawn_egg.egg-info/PKG-INFO
    writing top-level names to spawn_egg.egg-info/top_level.txt
    writing dependency_links to spawn_egg.egg-info/dependency_links.txt
    writing manifest file 'spawn_egg.egg-info/SOURCES.txt'
    reading manifest file 'spawn_egg.egg-info/SOURCES.txt'
    writing manifest file 'spawn_egg.egg-info/SOURCES.txt'
    installing library code to build/bdist.linux-x86_64/egg
    running install_lib
    running build_py
    creating build
    creating build/lib.linux-x86_64-2.7
    creating build/lib.linux-x86_64-2.7/spawn-egg
    copying spawn-egg/hello.py -> build/lib.linux-x86_64-2.7/spawn-egg
    copying spawn-egg/Base.py -> build/lib.linux-x86_64-2.7/spawn-egg
    copying spawn-egg/__init__.py -> build/lib.linux-x86_64-2.7/spawn-egg
    creating build/bdist.linux-x86_64
    creating build/bdist.linux-x86_64/egg
    creating build/bdist.linux-x86_64/egg/spawn-egg
    copying build/lib.linux-x86_64-2.7/spawn-egg/hello.py -> build/bdist.linux-x86_64/egg/spawn-egg
    copying build/lib.linux-x86_64-2.7/spawn-egg/Base.py -> build/bdist.linux-x86_64/egg/spawn-egg
    copying build/lib.linux-x86_64-2.7/spawn-egg/__init__.py -> build/bdist.linux-x86_64/egg/spawn-egg
    byte-compiling build/bdist.linux-x86_64/egg/spawn-egg/hello.py to hello.pyc
    byte-compiling build/bdist.linux-x86_64/egg/spawn-egg/Base.py to Base.pyc
    byte-compiling build/bdist.linux-x86_64/egg/spawn-egg/__init__.py to __init__.pyc
    creating build/bdist.linux-x86_64/egg/EGG-INFO
    copying spawn_egg.egg-info/PKG-INFO -> build/bdist.linux-x86_64/egg/EGG-INFO
    copying spawn_egg.egg-info/SOURCES.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
    copying spawn_egg.egg-info/dependency_links.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
    copying spawn_egg.egg-info/top_level.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
    zip_safe flag not set; analyzing archive contents...
    creating dist
    creating 'dist/spawn_egg-0.1.0-py2.7.egg' and adding 'build/bdist.linux-x86_64/egg' to it
    removing 'build/bdist.linux-x86_64/egg' (and everything under it)

    OK,egg文件已经在dist文件夹下生成好了,其实就是一个zip文件包,可以简单地用unzip命令check一下!

    ilab@iLab-Dev:~/project/dist$ unzip -l spawn_egg-0.1.0-py2.7.egg
    Archive: spawn_egg-0.1.0-py2.7.egg
     Length Date Time Name
    --------- ---------- ----- ----
     474 2015-06-10 15:31 spawn-egg/Base.pyc
     429 2015-06-10 15:31 spawn-egg/hello.pyc
     102 2015-06-10 15:04 spawn-egg/hello.py
     137 2015-06-10 15:31 spawn-egg/__init__.pyc
     44 2015-06-10 15:04 spawn-egg/Base.py
     0 2015-06-10 15:02 spawn-egg/__init__.py
     10 2015-06-10 15:31 EGG-INFO/top_level.txt
     199 2015-06-10 15:31 EGG-INFO/SOURCES.txt
     227 2015-06-10 15:31 EGG-INFO/PKG-INFO
     1 2015-06-10 15:31 EGG-INFO/dependency_links.txt
     1 2015-06-10 15:31 EGG-INFO/zip-safe
    --------- -------
     1624 11 files

    尝试安装一下

    ilab@iLab-Dev:~/project/dist$ sudo easy_install spawn_egg-0.1.0-py2.7.egg
    [sudo] password for ilab:
    Processing spawn_egg-0.1.0-py2.7.egg
    creating /usr/local/lib/python2.7/dist-packages/spawn_egg-0.1.0-py2.7.egg
    Extracting spawn_egg-0.1.0-py2.7.egg to /usr/local/lib/python2.7/dist-packages
    Adding spawn-egg 0.1.0 to easy-install.pth file
    
    Installed /usr/local/lib/python2.7/dist-packages/spawn_egg-0.1.0-py2.7.egg
    Processing dependencies for spawn-egg==0.1.0
    Finished processing dependencies for spawn-egg==0.1.0

    没有报错!这个时候/usr/local/lib/python2.7/dist-packages/就是您安装好的python包,你可以在这里删除/修改您的安装包。

    --------

    执行python setup.py bdist_egg命令之后,在dist目录下会生成egg文件,egg文件其实只是一个压缩包

    制作其他安装文件:

    python setup.py build  # 编译
    python setup.py sdist  # zip格式包
    python setup.py bdist_wininst # exe格式包
    python setup.py bdist_rpm # rpm格式包

  • 相关阅读:
    MybatisProperties注册IOC容器和初始化
    Springboot源码之application.yaml读取过程
    DataSource的注册容器和初始化
    修改ha_config配置文件
    读书笔记--Python基础教程 001
    Python实现购物车小程序
    Python3实现三级菜单
    实现用户登录并且输入错误三次后锁定该用户
    day1-python 的基础部分
    翻译:《实用的Python编程》06_02_Customizing_iteration
  • 原文地址:https://www.cnblogs.com/bonelee/p/11125173.html
Copyright © 2011-2022 走看看