• Python的egg包


    1、背景

    查看flower的源码,首先看到flower的主程序如下:

    #!/usr/local/sinasrv2/bin/python2.7
    # EASY-INSTALL-ENTRY-SCRIPT: 'flower==0.7.3','console_scripts','flower'
    __requires__ = 'flower==0.7.3'
    import sys 
    from pkg_resources import load_entry_point
    
    if __name__ == '__main__':
        sys.exit(
            load_entry_point('flower==0.7.3', 'console_scripts', 'flower')()
    

    load_entry_point,它的信息来源是entry_points.txt

    entry_points.txt来源呢?

    setup.py里面有entry_points 信息,会根据这些信息生成egg info目录,里面有entry_points.txt文件, 里面的内容就是setup.py里的entry_points信息

    setup(
        name='flower',
        version=get_package_version(),
        description='Celery Flower',
        long_description=open('README.rst').read(),
        author='Mher Movsisyan',
        author_email='mher.movsisyan@gmail.com',
        url='https://github.com/mher/flower',
        license='BSD',
        classifiers=classifiers,
        packages=find_packages(exclude=['tests', 'tests.*']),
        install_requires=install_requires,
        test_suite="tests",
        tests_require=get_requirements('test.txt'),
        package_data={'flower': ['templates/*', 'static/**/*', 'static/*.*']},
        entry_points={
            'console_scripts': [                                                                                                         
                'flower = flower.__main__:main',
            ],  
            'celery.commands': [
                'flower = flower.command:FlowerCommand',
            ],  
        },  
    )
    

      

    然后将封装一个python脚本

    说明flower脚本实际调用的是:

    两种启动方式

    [celery.commands]
    flower = flower.command:FlowerCommand
    
    [console_scripts]
    flower = flower.__main__:main
    

    2、如何制作一个egg包以及对应的setup.py如何写呢?

    2.1制作一个空的egg包目录以及setup.py文件

    首先建立工程目录egg-demo,初始化一个setup.py文件:

    [root@typhoeus79 ice_test_m 20141022]# tree -l
    .
    `-- egg-demo
        `-- setup.py
    
    1 directory, 1 file
    [root@typhoeus79 ice_test_m 20141022]# more ./egg-demo/setup.py 
    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    
    from setuptools import setup
    
    setup()
    

    写到这里,一个空的egg配置文件就写好了。

    setup的帮助文档:

    Help on function setup in module distutils.core:
    
    setup(**attrs)
        The gateway to the Distutils: do everything your setup script needs
        to do, in a highly flexible and user-driven way.  Briefly: create a
        Distribution instance; find and parse config files; parse the command
        line; run each Distutils command found there, customized by the options
        supplied to 'setup()' (as keyword arguments), in config files, and on
        the command line.
        
        The Distribution instance might be an instance of a class supplied via
        the 'distclass' keyword argument to 'setup'; if no such class is
        supplied, then the Distribution class (in dist.py) is instantiated.
        All other arguments to 'setup' (except for 'cmdclass') are used to set
        attributes of the Distribution instance.
        
        The 'cmdclass' argument, if supplied, is a dictionary mapping command
        names to command classes.  Each command encountered on the command line
        will be turned into a command class, which is in turn instantiated; any
        class found in 'cmdclass' is used in place of the default, which is
        (for command 'foo_bar') class 'foo_bar' in module
        'distutils.command.foo_bar'.  The command class must provide a
        'user_options' attribute which is a list of option specifiers for
        'distutils.fancy_getopt'.  Any command-line options between the current
        and the next command are used to set attributes of the current command
        object.
        
        When the entire command-line has been successfully parsed, calls the
        'run()' method on each command object in turn.  This method will be
        driven entirely by the Distribution object (which each command object
        has a reference to, thanks to its constructor), and the
        command-specific options that became attributes of each command
        object.
    

    setuptools的帮助文档:

    Help on package setuptools:
    
    NAME
        setuptools - Extensions to the 'distutils' for large or complex distributions
    
    FILE
        /usr/local/sinasrv2/lib/python2.7/site-packages/distribute-0.6.28-py2.7.egg/setuptools/__init__.py
    
    PACKAGE CONTENTS
        archive_util
        command (package)
        depends
        dist
        extension
        package_index
        sandbox
        script template
        script template (dev)
        tests (package)
    

      

    2.2执行命令生成egg包

    python setup.py bdist_egg

    setup.py可以支持很多命令:

    [root@typhoeus79 ice_test_m egg-demo]# python setup.py --help-commands
    Standard commands:
      build             build everything needed to install
      build_py          "build" pure Python modules (copy to build directory)
      build_ext         build C/C++ extensions (compile/link to build directory)
      build_clib        build C/C++ libraries used by Python extensions
      build_scripts     "build" scripts (copy and fixup #! line)
      clean             clean up temporary files from 'build' command
      install           install everything from build directory
      install_lib       install all Python modules (extensions and pure Python)
      install_headers   install C/C++ header files
      install_scripts   install scripts (Python or otherwise)
      install_data      install data files
      sdist             create a source distribution (tarball, zip file, etc.)
      register          register the distribution with the Python package index
      bdist             create a built (binary) distribution
      bdist_dumb        create a "dumb" built distribution
      bdist_rpm         create an RPM distribution
      bdist_wininst     create an executable installer for MS Windows
      upload            upload binary package to PyPI
    
    Extra commands:
      saveopts          save supplied options to setup.cfg or other config file
      compile_catalog   compile message catalogs to binary MO files
      develop           install package in 'development mode'
      easy_install      Find/get/install Python packages
      init_catalog      create a new catalog based on a POT file
      test              run unit tests after in-place build
      update_catalog    update message catalogs from a POT file
      setopt            set an option in setup.cfg or another config file
      install_egg_info  Install an .egg-info directory for the package
      rotate            delete older distributions, keeping N newest files
      egg_info          create a distribution's .egg-info directory
      alias             define a shortcut to invoke one or more commands
      extract_messages  extract localizable strings from the project code
      bdist_egg         create an "egg" distribution
    

      

    输出日志为:

    [root@typhoeus79 ice_test_m egg-demo]# python setup.py bdist_egg
    running bdist_egg
    running egg_info
    creating UNKNOWN.egg-info
    writing UNKNOWN.egg-info/PKG-INFO
    writing top-level names to UNKNOWN.egg-info/top_level.txt
    writing dependency_links to UNKNOWN.egg-info/dependency_links.txt
    writing manifest file 'UNKNOWN.egg-info/SOURCES.txt'
    reading manifest file 'UNKNOWN.egg-info/SOURCES.txt'
    writing manifest file 'UNKNOWN.egg-info/SOURCES.txt'
    installing library code to build/bdist.linux-x86_64/egg
    running install_lib
    warning: install_lib: 'build/lib' does not exist -- no Python modules to install
    creating build
    creating build/bdist.linux-x86_64
    creating build/bdist.linux-x86_64/egg
    creating build/bdist.linux-x86_64/egg/EGG-INFO
    copying UNKNOWN.egg-info/PKG-INFO -> build/bdist.linux-x86_64/egg/EGG-INFO
    copying UNKNOWN.egg-info/SOURCES.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
    copying UNKNOWN.egg-info/dependency_links.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
    copying UNKNOWN.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/UNKNOWN-0.0.0-py2.6.egg' and adding 'build/bdist.linux-x86_64/egg' to it
    removing 'build/bdist.linux-x86_64/egg' (and everything under it)
    

    再次查看egg-demo目录:

    [root@typhoeus79 ice_test_m egg-demo]# tree
    .
    |-- UNKNOWN.egg-info
    |   |-- PKG-INFO
    |   |-- SOURCES.txt
    |   |-- dependency_links.txt
    |   `-- top_level.txt
    |-- build
    |   `-- bdist.linux-x86_64
    |-- dist
    |   `-- UNKNOWN-0.0.0-py2.6.egg
    `-- setup.py
    

     在dist文件夹下,有一个egg文件:UNKNOWN-0.0.0-py2.6.egg,这说明产蛋成功!

    dist/
    `-- UNKNOWN-0.0.0-py2.6.egg
    

      

    egg文件是什么格式的呢?

    [root@typhoeus79 ice_test_m dist]# file UNKNOWN-0.0.0-py2.6.egg 
    UNKNOWN-0.0.0-py2.6.egg: Zip archive data, at least v2.0 to extract
    

    就是一个zip压缩包!看看其内部的结构

    [root@typhoeus79 ice_test_m dist]# unzip UNKNOWN-0.0.0-py2.6.egg 
    Archive:  UNKNOWN-0.0.0-py2.6.egg
      inflating: EGG-INFO/zip-safe       
      inflating: EGG-INFO/top_level.txt  
      inflating: EGG-INFO/dependency_links.txt  
      inflating: EGG-INFO/PKG-INFO       
      inflating: EGG-INFO/SOURCES.txt  
    [root@typhoeus79 ice_test_m dist]# tree ./EGG-INFO/
    ./EGG-INFO/
    |-- PKG-INFO
    |-- SOURCES.txt
    |-- dependency_links.txt
    |-- top_level.txt
    `-- zip-safe
    

    只有一个EGG-INFO文件夹,内含五个egg信息文件。

    这个egg名称未知,版本0.0.0。这是因为我们在setup里什么也没有设置。

    显然,这个egg什么也不能做。

    2.3 在egg包增加新功能-制作demo package

    在setup.py中,setup函数接收一系列属性作为配置参数。

    • name name是egg包的名称,也是寻找要打包的文件夹的名称,默认是UNKNOWN。
    • version 版本号,默认0.0.0
    • packages 这里要用到setuptools的另一个函数find_packages,顾名思义,find_packages用来将指定目录下的文件打包。
    • zip_safe 默认是False,这样在每次生成egg包时都会检查项目文件的内容,确保无误。

    还有一些描述性的属性,如description,long_description,author,author_email,license,keywords,platform,url等。

    [root@typhoeus79 ice_test_m egg-demo]# more setup.py 
    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    
    from setuptools import setup, find_packages
    
    setup(
            name = "demo",
            version="0.1.0",
            packages = find_packages(),
            zip_safe = False,
    
            description = "egg test demo.",
            long_description = "egg test demo, haha.",
            author = "amoblin",
            author_email = "amoblin@ossxp.com",
    
            license = "GPL",
            keywords = ("test", "egg"),
            platforms = "Independant",
            url = "",
            )
    

    在egg-demo目录下建立和上述name名称相同的目录demo,demo目录下写__init__.py文件:

     

    [root@typhoeus79 ice_test_m egg-demo]# tree ./demo/
    ./demo/
    `-- __init__.py
    
    0 directories, 1 file
    [root@typhoeus79 ice_test_m egg-demo]# more ./demo/__init__.py 
    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    
    def test():
        print "Hello, I'm amoblin."
    
    if __name__ == '__main__':
        test()
    

      

    再次生成egg包以后查看egg包信息:

    [root@typhoeus79 ice_test_m egg-demo]# ll
    总计 20
    drwxr-xr-x 4 root root 4096 10-22 14:34 build
    drwxr-xr-x 2 root root 4096 10-22 14:33 demo
    drwxr-xr-x 2 root root 4096 10-22 14:34 demo.egg-info
    drwxr-xr-x 2 root root 4096 10-22 14:34 dist
    -rw-r--r-- 1 root root  496 10-22 14:31 setup.py
    

     

    新的egg包里面的信息如下:

    [root@typhoeus79 ice_test_m dist]# unzip demo-0.1.0-py2.6.egg 
    Archive:  demo-0.1.0-py2.6.egg
      inflating: EGG-INFO/not-zip-safe   
      inflating: EGG-INFO/top_level.txt  
      inflating: EGG-INFO/dependency_links.txt  
      inflating: EGG-INFO/PKG-INFO       
      inflating: EGG-INFO/SOURCES.txt    
      inflating: demo/__init__.pyc       
      inflating: demo/__init__.py 
    

      

    现在可以安装了体验一下!!

    [root@typhoeus79 ice_test_m egg-demo]# python setup.py install
    running install
    running bdist_egg
    running egg_info
    writing demo.egg-info/PKG-INFO
    writing top-level names to demo.egg-info/top_level.txt
    writing dependency_links to demo.egg-info/dependency_links.txt
    reading manifest file 'demo.egg-info/SOURCES.txt'
    writing manifest file 'demo.egg-info/SOURCES.txt'
    installing library code to build/bdist.linux-x86_64/egg
    running install_lib
    running build_py
    creating build/bdist.linux-x86_64/egg
    creating build/bdist.linux-x86_64/egg/demo
    copying build/lib/demo/__init__.py -> build/bdist.linux-x86_64/egg/demo
    byte-compiling build/bdist.linux-x86_64/egg/demo/__init__.py to __init__.pyc
    creating build/bdist.linux-x86_64/egg/EGG-INFO
    copying demo.egg-info/PKG-INFO -> build/bdist.linux-x86_64/egg/EGG-INFO
    copying demo.egg-info/SOURCES.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
    copying demo.egg-info/dependency_links.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
    copying demo.egg-info/not-zip-safe -> build/bdist.linux-x86_64/egg/EGG-INFO
    copying demo.egg-info/top_level.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
    creating 'dist/demo-0.1.0-py2.6.egg' and adding 'build/bdist.linux-x86_64/egg' to it
    removing 'build/bdist.linux-x86_64/egg' (and everything under it)
    Processing demo-0.1.0-py2.6.egg
    creating /usr/lib/python2.6/site-packages/demo-0.1.0-py2.6.egg
    Extracting demo-0.1.0-py2.6.egg to /usr/lib/python2.6/site-packages
    Adding demo 0.1.0 to easy-install.pth file
    
    Installed /usr/lib/python2.6/site-packages/demo-0.1.0-py2.6.egg
    Processing dependencies for demo==0.1.0
    Finished processing dependencies for demo==0.1.0
    

      

    安装完毕!接下来我们就可以直接通过import来使用啦!

    >>> from demo import test
    >>> help(test)
    
    >>> test()
    Hello, I'm amoblin.
    

      

    源程序都放在src目录下,所以接下来将demo文件夹移动到src里。但这样也要修改setup.py文件,修改find_packages函数中参数为’src’,同时增加package_dir参数:

    packages=find_packages('src'),
    package_dir = {'':'src'}

    这样告诉setuptools在src目录下找包,而不是原来默认的工程根目录。

    2.4如何删除egg包

    找到package放的位置

    >>> print sys.path[1]
    /usr/lib/python2.6/site-packages/setuptools-0.6c11-py2.6.egg
    

    存在这个egg包  

    [root@typhoeus79 ice_test_m site-packages]# ll /usr/lib/python2.6/site-packages |grep demo
    drwxr-xr-x 4 root root   4096 10-22 14:36 demo-0.1.0-py2.6.egg
    [root@typhoeus79 ice_test_m site-packages]# cat easy-install.pth|grep demo
    ./demo-0.1.0-py2.6.egg
    

      

    卸载egg文件很简单,首先将包含此egg的行从easy-install.pth中删除,然后删除egg文件夹即可。

    3、参考资料

    1、http://www.cnblogs.com/itech/archive/2011/02/13/1953268.html

    2、http://zhiwei.li/text/2011/06/load_entry_point%E5%92%8Csetup-egg/

    3、http://django-china.cn/topic/90/

    4、http://blog.habnab.it/blog/2013/07/21/python-packages-and-you/

  • 相关阅读:
    java高并发程序设计模式-并发级别:阻塞、无障碍、无锁、无等待【转载】
    Java创建线程的三种主要方式
    Java乐观锁实现之CAS操作
    Java解释执行和编译执行
    手把手教你使用百度大脑地址识别API
    详解百度大脑EdgeBoard出色的视频处理技术
    一步到位!!百度大脑语音合成快速搞定会员到访提醒功能
    一文带你了解百度大脑云狐语音全攻略(附代码)
    AI小程序之语音听写来了,十分钟掌握百度大脑语音听写全攻略!!
    快速上手百度大脑EasyDL专业版·物体检测模型(附代码)
  • 原文地址:https://www.cnblogs.com/gsblog/p/4042954.html
Copyright © 2020-2023  润新知