Python包管理工具setuptools详解
是什么
setuptools是Python distutils增强版的集合,它可以帮助我们更简单的创建和分发Python包
1.创建一个简单的包
cd /tmp
mkdir demo
cd demo
在demo中创建一个setup.py文件,写入
from setuptools import setup, find_packages
setup(
name = "demo", #包名,真正调用的不是这个包名,这只是一个宏观的包名
version = "0.1", #版本号
packages = find_packages(), #所有包含的其他包
)
执行 python setup.py bdist_egg 即可打包一个包
demo
|-- build
| `-- bdist.linux-x86_64
|-- demo.egg-info
| |-- dependency_links.txt
| |-- PKG-INFO
| |-- SOURCES.txt
| `-- top_level.txt
|-- dist
| `-- demo-0.1-py2.7.egg
`-- setup.py
在dist中生成的是egg包
file dist/demo-0.1-py2.7.egg
dist/demo-0.1-py2.7.egg: Zip archive data, at least v2.0 to extract
看一下生成的.egg文件,是个zip包,解开看看先
upzip -l dist/demo-0.1-py2.7.egg
Archive: dist/demo-0.1-py2.7.egg
Length Date Time Name
--------- ---------- ----- ----
1 2013-06-07 22:03 EGG-INFO/dependency_links.txt
1 2013-06-07 22:03 EGG-INFO/zip-safe
120 2013-06-07 22:03 EGG-INFO/SOURCES.txt
1 2013-06-07 22:03 EGG-INFO/top_level.txt
176 2013-06-07 22:03 EGG-INFO/PKG-INFO
--------- -------
299 5 files
2.给包增加内容
上面生成的egg中没有实质的内容,显然谁也用不了,现在我们稍微调色一下,增加一点内容。
在demo中执行mkdir demo,再创建一个目录,在这个demo目录中创建一个init.py的文件,表示这个目录是一个包,然后写入:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
def test():
print "hello world!"
if __name__ == '__main__':
test()
现在的主目录结构为下:
demo
|-- demo
| `-- __init__.py
`-- setup.py
再次执行python setup.py bdist_egg后,再看egg包
Archive: dist/demo-0.1-py2.7.egg
Length Date Time Name
--------- ---------- ----- ----
1 2013-06-07 22:23 EGG-INFO/dependency_links.txt
1 2013-06-07 22:23 EGG-INFO/zip-safe
137 2013-06-07 22:23 EGG-INFO/SOURCES.txt
5 2013-06-07 22:23 EGG-INFO/top_level.txt
176 2013-06-07 22:23 EGG-INFO/PKG-INFO
95 2013-06-07 22:21 demo/__init__.py
338 2013-06-07 22:23 demo/__init__.pyc
--------- -------
753 7 files
这回包内多了demo目录,已经有了我们自己的东西了,安装体验一下。
python setup.py install
这个命令会将我们创建的egg安装到python的dist-packages目录下,我这里的位置在
tree /usr/local/lib/python2.7/dist-packages/demo-0.1-py2.7.egg
查看一下它的结构:
/usr/local/lib/python2.7/dist-packages/demo-0.1-py2.7.egg
|-- demo
| |-- __init__.py
| `-- __init__.pyc
`-- EGG-INFO
|-- dependency_links.txt
|-- PKG-INFO
|-- SOURCES.txt
|-- top_level.txt
`-- zip-safe
打开python终端或者ipython都行,直接导入我们的包
>>> import demo
>>> demo.test()
hello world!
>>>
好了,执行成功!
3.setuptools进阶
使用find_packages()
对于简单工程来说,手动增加packages参数很容易,刚刚我们用到了这个函数,它默认在和setup.py同一目录下搜索各个含有init.py的包。其实我们可以将包统一放在一个src目录中,另外,这个包内可能还有aaa.txt文件和data数据文件夹。
demo
├── setup.py
└── src
└── demo
├── __init__.py
├── aaa.txt
└── data
├── abc.dat
└── abcd.dat
如果不加控制,则setuptools只会将init.py加入到egg中,想要将这些文件都添加,需要修改setup.py
from setuptools import setup, find_packages
setup(
packages = find_packages('src'), # 包含所有src中的包
package_dir = {'':'src'}, # 告诉distutils包都在src下
package_data = {
# 任何包中含有.txt文件,都包含它
'': ['*.txt'],
# 包含demo包data文件夹中的 *.dat文件
'demo': ['data/*.dat'],
}
)
这样,在生成的egg中就包含了所需文件了。看看:
Archive: dist/demo-0.0.1-py2.7.egg
Length Date Time Name
-------- ---- ---- ----
88 06-07-13 23:40 demo/__init__.py
347 06-07-13 23:52 demo/__init__.pyc
0 06-07-13 23:45 demo/aaa.txt
0 06-07-13 23:46 demo/data/abc.dat
0 06-07-13 23:46 demo/data/abcd.dat
1 06-07-13 23:52 EGG-INFO/dependency_links.txt
178 06-07-13 23:52 EGG-INFO/PKG-INFO
157 06-07-13 23:52 EGG-INFO/SOURCES.txt
5 06-07-13 23:52 EGG-INFO/top_level.txt
1 06-07-13 23:52 EGG-INFO/zip-safe
-------- -------
777 10 files
也可以通过exclude来排除它
find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"])
1)包含所有包内文件
from setuptools import setup, find_packages
setup(
...
include_package_data = True
)
2)包含一部分,排除一部分
from setuptools import setup, find_packages
setup(
...
packages = find_packages('src'),
package_dir = {'':'src'},
include_package_data = True,
# 排除所有 README.txt
exclude_package_data = { '': ['README.txt'] },
)