如何组织Python模块以支持2.x和3.x发布到PyPI
我有一个Python模块,想把它上传到PyPI(Python的包管理网站)。目前这个模块可以在Python 2.x上运行。现在为3.x版本写一个也应该不难。
不过,我按照以下这些地方的指南来制作模块:
但是我不太清楚怎么支持不同Python版本的多个源代码分发,也不太清楚PyPI是否能支持这个。我想象中,我可能需要为以下版本准备不同的代码:
- 2.x
- 2.6(可能作为一个特殊情况,使用新的缓冲区API)
- 3.x
那么,如何在PyPI上设置一个Python模块,让用户可以这样做:
easy_install modulename
无论用户使用的是2.x还是3.x,都能安装到合适的版本呢?
2 个回答
最简单的解决办法就是使用一个统一的源代码包。
我发现httplib2
的setup.py
文件似乎有一种优雅的方法来支持Python 2.x和3.x。所以我决定借鉴这个方法。
我的任务是制作一个单一的setup.py
文件,用于打包分发,能够兼容所有支持的Python版本。这样,你就可以用同一个setup.py
来做:
python2 setup.py install
还有
python3 setup.py install
应该可以保持setup.py
简单到可以被所有支持的Python版本解析。我已经成功地做到这一点,创建了一个支持2.4到2.6以及3.1的包cobs
。这个包包含了纯Python代码(Python 2.x和3.x的代码是分开的)以及C扩展,分别为2.x和3.x编写。
具体步骤如下:
1) 我把Python 2.x的代码放在一个python2
子目录里,把Python 3.x的代码放在python3
子目录里。
2) 我把2.x和3.x的C扩展代码放在python2
和python3
下的src
目录里。
所以,目录结构是:
root
|
+--python2
| |
| +--src
|
+--python3
| |
| +--src
|
+--setup.py
+--MANIFEST.in
3) 在setup.py
的顶部,我添加了这些行:
if sys.version_info[0] == 2:
base_dir = 'python2'
elif sys.version_info[0] == 3:
base_dir = 'python3'
4) 在调用setup
时,我像平常一样指定了包:
setup(
...
packages=[ 'cobs', 'cobs.cobs', 'cobs.cobsr', ],
5) 我使用package_dir
选项指定了Python代码的基础目录(参考步骤3中的base_dir
):
package_dir={
'cobs' : base_dir + '/cobs',
},
6) 对于C扩展,我给出了路径:
ext_modules=[
Extension('cobs.cobs._cobs_ext', [ base_dir + '/src/_cobs_ext.c', ]),
Extension('cobs.cobsr._cobsr_ext', [ base_dir + '/src/_cobsr_ext.c', ]),
],
这就是setup.py
的主要内容。这个setup.py
文件可以被Python 2.x和3.x解析。
7) 最后,如果你使用以下命令构建源分发:
python2 setup.py sdist
那么默认情况下,它只会拉取构建该Python版本所需的文件。例如,在上面的情况下,你只会在源分发中得到python2
下的文件,而不会得到python3
下的文件。但如果你想要一个完整的源分发,你需要包含2.x和3.x的文件。为此,创建一个MANIFEST.in
文件,内容类似于:
include *.txt
recursive-include python2 *
recursive-include python3 *