自定义distutils命令
我有一个叫“example”的库,我想把它安装到我的全局包目录里。不过,我希望能安装两个版本,一个用于生产环境,另一个用于测试(因为我有一个网页应用和其他一些东西是这样管理版本的)。
有没有办法可以指定,比如说“python setup.py stage”,这样不仅可以把不同的版本安装到包目录里,还能把模块的名字从“example”改成“example_stage”或者类似的名字呢?
如果distutils做不到这个,还有其他工具可以实现吗?
4 个回答
如果你想使用多个版本的东西,可以试试 virtualenv 和 virtualenvwrapper,这两个工具会很有帮助。
这可以通过在setup.py文件中继承distutils.core.Command来轻松实现。
举个例子:
from distutils.core import setup, Command
import os, sys
class CleanCommand(Command):
description = "custom clean command that forcefully removes dist/build directories"
user_options = []
def initialize_options(self):
self.cwd = None
def finalize_options(self):
self.cwd = os.getcwd()
def run(self):
assert os.getcwd() == self.cwd, 'Must be in package root: %s' % self.cwd
os.system('rm -rf ./build ./dist')
要启用这个命令,你必须在setup()中引用它:
setup(
# stuff omitted for conciseness.
cmdclass={
'clean': CleanCommand
}
注意,你也可以通过这种方式覆盖内置命令,比如我对'clean'做的修改。(我不喜欢内置版本留下的'dist'和'build'目录。)
% python setup.py --help-commands | grep clean
clean custom clean command that forcefully removes dist/build dirs.
这里有一些常用的约定:
- 你可以通过user_options来指定任何命令行参数。
- 你可以用initialize_options()方法声明你会用到的变量,这个方法在初始化后被调用,用来设置你自定义的命名空间。
- finalize_options()方法在run()之前被调用。
- 命令的主要内容会在run()中执行,所以确保在那之前做好其他准备工作。
最好的例子就是查看默认命令的源代码,比如在PYTHON_DIR/distutils/command目录下的install.py或build.py。
当然,你可以通过新的命令来扩展distutils。在你的distutils配置文件中,添加以下内容:
[global]
command-packages=foo.bar
这个配置可以放在distutils.cfg
文件中,或者放在你家目录下的..pydistutils.cfg
(在Windows上不要加点),或者放在当前目录的setup.cfg
文件中。
接下来,你需要在Python的site-packages目录下创建一个名为foo.bar的包。
然后在这个包里,你需要添加实现你想要的新命令的类,比如stage
,这个类要继承自distutils.cmd。虽然文档不太详细,但有很多例子,因为所有现有的distutils命令都是这样构建的。