Python setup.py运行shell脚本

时间:2013-07-26 17:55:19

标签: python setuptools

我需要在'sdist'阶段运行我自己的脚本,同时创建Python包。 我写了以下脚本。你知道更好的方法吗?您能否推荐更好的一个或链接到setuptools上的官方文档,其中已经解释了这个时刻?

import subprocess
import sys

from setuptools import setup, find_packages, os

if 'sdist' in sys.argv:
    cwd = os.getcwd()
    os.chdir('website/static/stylesheets/')
    result = subprocess.call("scss --update --compass ./*.scss", shell=True)
    if result != 0:
        exit(1)
    os.chdir(cwd)

setup(name = "site",
    author="Vladimir Ignatev",
    author_email="mail@gmail.com",
    version="0.1",
    packages=find_packages(),
    include_package_data=True,
    zip_safe=True,
)

2 个答案:

答案 0 :(得分:3)

虽然这已经很晚了,但这是一个解决方案提案。

基本上,它只是将distutils' sdist命令,添加自定义逻辑并在设置函数中注册。 Unfortunately, the official documentation to this topic is kind of vague and laconic; Extending Distutils至少提供了一个很小的例子。我发现阅读distutils.command包中的模块代码以了解实际命令是如何实现的更好。

要执行任意命令,您可以使用执行传递的输入字符串的方法distutils.cmd.Command::spawn,如果命令的退出代码不为零,则引发DistutilsExecError

from distutils.command.sdist import sdist as sdist_orig
from distutils.errors import DistutilsExecError

from setuptools import setup  


class sdist(sdist_orig):

    def run(self):
        try:
            self.spawn(['ls', '-l'])
        except DistutilsExecError:
            self.warn('listing directory failed')
        super().run()


setup(name='spam',
    version='0.1',
    packages=[],
    cmdclass={
        'sdist': sdist
    }
)

运行上面的安装脚本会产生:

$ python setup.py sdist
running sdist
ls -l
total 24
-rw-r--r--  1 hoefling  staff   52 23 Dez 19:06 MANIFEST
drwxr-xr-x  3 hoefling  staff   96 23 Dez 19:06 dist
-rw-r--r--  1 hoefling  staff  484 23 Dez 19:07 setup.py
running check
...
writing manifest file 'MANIFEST'
creating spam-0.1
making hard links in spam-0.1...
hard linking setup.py -> spam-0.1
Creating tar archive
removing 'spam-0.1' (and everything under it)

重用命令

这是(尽管简化)我们在项目中使用的命令的实际示例,这些命令用于NodeJS项目并调用yarn

import distutils
import os
import pathlib
import setuptools

_YARN_CMD_SEP = ';'

_HELP_MSG_SUBCMD = (
    'yarn subcommands to execute (separated '
    'by {})'.format(_YARN_CMD_SEP)
)

_HELP_MSG_PREFIX = (
    'path to directory containing package.json. '
    'If not set, current directory is assumed.'
)


class yarn(setuptools.Command):

    description = ('runs yarn commands. Assumes yarn is '
                   'already installed by the user.')

    user_options = [
        ('subcommands=', None, _HELP_MSG_SUBCMD),
        ('prefix=', None, _HELP_MSG_PREFIX),
    ]

    def initialize_options(self) -> None:
        self.subcommands = []
        self.prefix = None  # type: pathlib.Path

    def finalize_options(self) -> None:
        self.subcommands = [
            cmd.strip() for cmd in str(self.subcommands).split(self._YARN_CMD_SEP)
        ]
        self.prefix = pathlib.Path(self.prefix) if self.prefix else pathlib.Path()

    def run(self) -> None:
        cwd = pathlib.Path().absolute()
        os.chdir(str(self.prefix.absolute()))  # change to prefix dir
        for cmd in self.subcommands:
            self.announce('running yarn {} ...'.format(cmd), level=distutils.log.INFO)
            self.spawn(['yarn'] + cmd.split(' '))
        os.chdir(str(cwd))  # change back to our previous dir

使用示例:

$ python setup.py yarn --prefix=. --subcommands="add leftpad; remove leftpad"
running yarn
running yarn add leftpad ...
yarn add leftpad
yarn add v1.3.2
warning package.json: No license field
warning No license field
[1/4]   Resolving packages...
[2/4]   Fetching packages...
[3/4]   Linking dependencies...
[4/4]   Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency.
└─ leftpad@0.0.1
warning No license field
✨  Done in 0.33s.
running yarn remove leftpad ...
yarn remove leftpad
yarn remove v1.3.2
warning package.json: No license field
[1/2] Removing module leftpad...
[2/2] Regenerating lockfile and installing missing dependencies...
warning No license field
success Uninstalled packages.
✨  Done in 0.13s.

您还可以在命令链中使用yarn作为其他命令:python setup.py yarn test sdist等。

答案 1 :(得分:-3)

也许尝试distutils我认为它比setuptools更新。