python的打包方式有很多种,而且针对不同的平台又有很多不同的方式,这里指针对linux平台进行介绍……
1 python打包工具选择
关于python打包相关的工具,这篇文档有一个列表,其中打包工具主要分为pip, dislib, setuptools, distribute(已经于setuptools合并)。还有博客也是关于python 打包工具的,这篇博客对于python的各种打包工具,及其优缺点写的很详细,里面说的Distutils2是更为先进的打包工具,但是适用范围还不是太广泛,这里先不做研究了。经过综合对比,目前选中setuptools和pip这两个个比较成熟的打包工具,下面就对他们用法和原理分别进行详细的介绍。
2 setuptools
setuptools的官方文档地址
首先来一个简单的上手过程,通过这个过程可以快速了解setuptools怎么用的,详情请移步博客python egg 学习笔记
看完这个教程就能自己做一个简单的包了,但是这里只是涉及了一种包,就是python import 引过来,然后调用其中的函数,还有一种也很普遍的方式就是命令行方式,例如jekyll命令,sentry命令等,这种方式其实可以参考这篇文档。跟随这两篇博客基本就可以满足我们的需求了
这里对其安装步骤进行一下总结:
2.1, 安装setuptools
1 | $ wget http://peak.telecommunity.com/dist/ez_setup.py |
其实安装的方式有很多种,具体方法参见前面提到的博客
2.2, 建立一个工程
1 | $ mkdir mypackage |
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
2python 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
71 #!/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 | ├── setup.py |
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
到这里整个配置文件的写法,源代码的写法,打包到本地和打包到远程,本地安装和远程安装都介绍完了。