python的打包方式有很多种,而且针对不同的平台又有很多不同的方式,这里指针对linux平台进行介绍……
1 python打包工具选择 关于python打包相关的工具,这篇文档有一个列表 ,其中打包工具主要分为pip, dislib, setuptools, distribute(已经于setuptools合并)。还有博客也是关于python 打包工具的,这篇博客 对于python的各种打包工具,及其优缺点写的很详细,里面说的Distutils2是更为先进的打包工具,但是适用范围还不是太广泛,这里先不做研究了。经过综合对比,目前选中setuptools和pip这两个个比较成熟的打包工具,下面就对他们用法和原理分别进行详细的介绍。
setuptools的官方文档地址 首先来一个简单的上手过程,通过这个过程可以快速了解setuptools怎么用的,详情请移步博客python egg 学习笔记 看完这个教程就能自己做一个简单的包了,但是这里只是涉及了一种包,就是python import 引过来,然后调用其中的函数,还有一种也很普遍的方式就是命令行方式,例如jekyll命令,sentry命令等,这种方式其实可以参考这篇文档 。跟随这两篇博客基本就可以满足我们的需求了 这里对其安装步骤进行一下总结:
1 2 $ wget http://peak.telecommunity.com/dist/ez_setup.py $ sudo python ez_setup.py
其实安装的方式有很多种,具体方法参见前面提到的博客
2.2, 建立一个工程 1 2 3 $ mkdir mypackage $ cd mypackage $ touch setup.py
setup.py的内容如下:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 1 #setup.py 2 #!/usr/bin/env python 3 #-*- coding:utf-8 -*- 4 5 from setuptools import setup, find_packages 6 7 setup( 8 name = "myproject", 9 version="0.1.0", 10 packages = find_packages(), 11 zip_safe = False, 12 13 description = "egg test demo.", 14 long_description = "egg test demo, haha.", 15 author = "sean", 16 author_email = "seanerchen@gmail.com", 17 18 license = "GPL", 19 keywords = ("test", "egg"), 20 platforms = "Independant", 21 url = "", 22 )
第8行表示这个工程的名称,第9行是这个工程的版本号,第10行表示对指定目录的文件打包,其他信息请查看相关文档,这里先对用到的配置项进行讲解
2.3, 通过命令行打包到本地 这是一个空的工程就建好了,我们可以通过一条简单的命令对它进行打包了:1 2 python setup.py bdist_egg #python setup.py bdist 命令也可以。它们之间的区别?
命令执行后,myproject目录的的结构如下:1 2 3 4 5 6 7 8 9 10 11 12 . ├── build │ └── bdist.linux-x86_64 ├── dist │ └── myproject-0.1.0-py2.6.egg ├── myproject.egg-info │ ├── dependency_links.txt │ ├── not-zip-safe │ ├── PKG-INFO │ ├── SOURCES.txt │ └── top_level.txt └── setup.py
我们可以看到在dist文件夹下生成了一个egg文件,通过使用命令file可以查看这个文件的格式:1 2 $ file dist/myproject-0.1.0-py2.6.egg dist/myproject-0.1.0-py2.6.egg: Zip archive data, at least v2.0 to extract
其实egg文件就一个压缩包,关于egg的介绍请参考这篇博客
2.4, 写自己的程序并打包到本地 在当前目录下建立一个文件夹,名字与setup.py里写的name字段保持一致,然后在进入目录,创建init .py文件1 2 3 $ mkdir myproject $ cd myproject $ touch __init__.py
文件__init__.py内容如下:1 2 3 4 5 6 7 1 #!/usr/bin/env python 2 #-*-coding:utf-8-*- 3 4 def test(): 5 print "Hello World!" 6 if __name__ == '__main__': 7 test()
再次运行生成egg的命令:
1 python setup.py bdist_egg
这时整个目录结构变成了下面的情况:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 . ├── build │ ├── bdist.linux-x86_64 │ └── lib │ └── myproject │ └── __init__.py ├── dist │ └── myproject-0.1.0-py2.6.egg ├── myproject │ └── __init__.py ├── myproject.egg-info │ ├── dependency_links.txt │ ├── not-zip-safe │ ├── PKG-INFO │ ├── SOURCES.txt │ └── top_level.txt └── setup.py
可以看一下这个egg文件的内容:1 2 3 4 5 6 7 8 9 10 11 12 13 $ unzip -l dist/myproject-0.1.0-py2.6.egg Archive: dist/myproject-0.1.0-py2.6.egg Length Date Time Name --------- ---------- ----- ---- 118 11-01-2013 14:35 myproject/__init__.py 354 11-01-2013 14:35 myproject/__init__.pyc 232 11-01-2013 14:35 EGG-INFO/PKG-INFO 194 11-01-2013 14:35 EGG-INFO/SOURCES.txt 1 11-01-2013 14:35 EGG-INFO/dependency_links.txt 1 10-21-2013 12:29 EGG-INFO/not-zip-safe 10 11-01-2013 14:35 EGG-INFO/top_level.txt --------- ------- 910 7 files
可以看到里面多出来一个myproject文件夹和它所包含的文件,正是我们刚才创建的。
2.5, 打包到远程 这里我们只是把打的包放在了本地, 也可以根据前面讲的打包到远程的源中,这里结合前面的博客把这个包发送到私有源,命令如下:1 2 3 4 5 6 7 8 $ python setup.py sdist upload -r local running sdist running egg_info ... removing 'myproject-0.1.0' (and everything under it) running upload Submitting dist/myproject-0.1.0.tar.gz to http://127.0.0.1:3141 Server response (200): OK
这样我们就可以把本地的包上传到了远程的私有源local
上供其他人使用了。
2.6, 安装和使用 安装可以分为本地安装和远程安装。这个和之前私有源建立的博客中讲的一样,具体方式如下: 1,本地安装: 1 2 3 4 5 6 7 8 9 10 11 $ sudo python setup.py install running install running bdist_egg running egg_info ... ... Installed /root/.local/lib/python2.6/site-packages/myproject-0.1.0-py2.6.egg Processing dependencies for myproject==0.1.0 Finished processing dependencies for myproject==0.1.0 $ python -c "from myproject import test; test()" Hello World!
可以看到我们的包已经被安装了,并且可以运行我们之前在包里封装的方法。 2,远程安装: 我们可以安装远程私有源的包到本地:1 2 3 4 5 6 7 8 9 10 11 12 13 14 # 安装远程包到本地 $ easy_install -i http://10.11.215.61:3141/simple/ myproject Searching for myproject Reading http://10.11.215.61:3141/simple/myproject/ Best match: myproject 0.1.0 Downloading http://10.11.215.61:3141/packages/myproject-0.1.0.tar.gz Processing myproject-0.1.0.tar.gz Writing /tmp/easy_install-szH61Z/myproject-0.1.0/setup.cfg Running myproject-0.1.0/setup.py -q bdist_egg --dist-dir /tmp/easy_install-szH61Z/myproject-0.1.0/egg-dist-tmp-aI8vPL Adding myproject 0.1.0 to easy-install.pth file Installed /usr/lib/python2.6/site-packages/myproject-0.1.0-py2.6.egg Processing dependencies for myproject Finished processing dependencies for myproject
这时刚才上传到私有源的包就安装在了本地,安装路径可以从安装的信息中看到。安装的路径为:/usr/lib/python2.6/site-packages/myproject-0.1.0-py2.6.egg
2.7, 代码结构规划 一般情况下为了使代码看起来更加有条理,我们把源代码放到src文件夹下。首先把myproject文件夹移动到src中,然后删除以前产生的文件,只保留自己写的问文件,其结构大致如下:
1 2 3 4 5 ├── setup.py └── src └── myproject ├── __init__.py └── __init__.pyc
setup.py内容也要修改,修改默认的搜索路径为src,而不是从根目录开始,内容如下:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 # setup.py # !/usr/bin/env python # -*- coding:utf-8 -*- from setuptools import setup, find_packages setup( name = "myproject", version="0.1.0", packages = find_packages('src'), package_dir = {'':'src'}, zip_safe = False, description = "egg test demo.", long_description = "egg test demo, haha.", author = "sean", author_email = "seanerchen@gmail.com", license = "GPL", keywords = ("test", "egg"), platforms = "Independant", url = "", )
然后运行命令生成egg等文件:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 $ python setup.py bdist_egg $ tree . ├── build │ ├── bdist.linux-x86_64 │ └── lib │ └── myproject │ └── __init__.py ├── dist │ └── myproject-0.1.0-py2.6.egg ├── setup.py └── src ├── myproject │ ├── __init__.py │ └── __init__.pyc └── myproject.egg-info ├── dependency_links.txt ├── not-zip-safe ├── PKG-INFO ├── SOURCES.txt └── top_level.txt 8 directories, 10 files
然后用同样的方式进行安装运行,依然没有问题。
2.8, 卸载程序 安装过的python包,如果要删除该如何做呢? 首先要找到easy-install.pth文件,这个文件是自动查询安装包的路径的文件,如果把安装包的路径从这个文件中去掉,将找不到要使用的包 当运行安装程序发现最后几行信息:1 2 3 4 5 6 7 8 9 10 $ python setup.py install ... Processing myproject-0.1.0-py2.6.egg creating /root/.local/lib/python2.6/site-packages/myproject-0.1.0-py2.6.egg Extracting myproject-0.1.0-py2.6.egg to /root/.local/lib/python2.6/site-packages Adding myproject 0.1.0 to easy-install.pth file Installed /root/.local/lib/python2.6/site-packages/myproject-0.1.0-py2.6.egg Processing dependencies for myproject==0.1.0 Finished processing dependencies for myproject==0.1.0
可以看出包的安装路径和包的路径信息都能找到,删除相应的包和路径就会发现无法使用该包了。 打开文件easy-install.pth,删除./myproject-0.1.0-py2.6.egg这一行,或者直接删除安装好的egg包,再次运行python时就会提示找不到该包1 2 3 4 >>> from myproject import test Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named myproject
到这里整个配置文件的写法,源代码的写法,打包到本地和打包到远程,本地安装和远程安装都介绍完了。