如何在setup.py中执行自定义构建步骤?

17 投票
2 回答
13043 浏览
提问于 2025-04-17 13:18

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 的一个子命令。关于这个问题的更多细节,可以参考其他对类似或重复问题的回答,比如这个:

https://stackoverflow.com/a/1321345/150999

撰写回答