如何在setup.py中执行自定义构建步骤?
distutils
模块可以让你把资源文件和Python模块一起打包和安装。那么,如果这些资源文件是在构建过程中生成的,应该怎么正确地包含它们呢?
举个例子,假设这个项目是一个网页应用,它里面有一些CoffeeScript源文件,这些文件需要先编译成JavaScript,然后再包含在Python包里。有没有办法把这个过程整合进正常的sdist/bdist流程中呢?
2 个回答
16
我花了不少时间才搞明白这个问题,网上的各种建议都有问题——要么会导致依赖项安装失败,要么在pip中无法使用等等。下面是我的解决方案:
在setup.py文件中:
from setuptools import setup, find_packages
from setuptools.command.install import install
from distutils.command.install import install as _install
class install_(install):
# inject your own code into this func as you see fit
def run(self):
ret = None
if self.old_and_unmanageable or self.single_version_externally_managed:
ret = _install.run(self)
else:
caller = sys._getframe(2)
caller_module = caller.f_globals.get('__name__','')
caller_name = caller.f_code.co_name
if caller_module != 'distutils.dist' or caller_name!='run_commands':
_install.run(self)
else:
self.do_egg_install()
# This is just an example, a post-install hook
# It's a nice way to get at your installed module though
import site
site.addsitedir(self.install_lib)
sys.path.insert(0, self.install_lib)
from mymodule import install_hooks
install_hooks.post_install()
return ret
然后,在你调用setup函数的时候,传入这个参数:
cmdclass={'install': install_}
你也可以用同样的思路来处理构建,而不是安装,自己写个装饰器让它更简单等等。这些方法已经通过pip测试过,也可以直接用'python setup.py install'来调用。
2
最好的办法是写一个自定义的 build_coffeescript 命令,然后把它作为 build 的一个子命令。关于这个问题的更多细节,可以参考其他对类似或重复问题的回答,比如这个: