当前位置:  开发笔记 > 编程语言 > 正文

distutils:如何将用户定义的参数传递给setup.py?

如何解决《distutils:如何将用户定义的参数传递给setup.py?》经验,为你挑选了5个好方法。

请提示我如何将命令行和setup.cfg配置文件中的用户定义参数传递给distutils的setup.py脚本.我想编写一个setup.py脚本,它接受我的包特定参数.例如:

python setup.py install -foo myfoo

谢谢你,
Mher



1> Cerin..:

由于Setuptools/Distuils的记录非常糟糕,我自己也找不到答案.但最终我偶然发现了这个例子.此外,这个类似的问题很有帮助.基本上,带有选项的自定义命令如下所示:

from distutils.core import setup, Command

class InstallCommand(Command):
    description = "Installs the foo."
    user_options = [
        ('foo=', None, 'Specify the foo to bar.'),
    ]
    def initialize_options(self):
        self.foo = None
    def finalize_options(self):
        assert self.foo in (None, 'myFoo', 'myFoo2'), 'Invalid foo!'
    def run(self):
        install_all_the_things()

setup(
    ...,
    cmdclass={
        'install': InstallCommand,
    }
)


嗨,你运行的命令行是什么传递给foo =什么?
这对我很有用,但是如何指定多个`user_options`?你如何扩展它?

2> totaam..:

这是一个非常简单的解决方案,您需要做的就是sys.argv在调用distutils之前过滤掉并自己处理它setup(..).像这样的东西:

if "--foo" in sys.argv:
    do_foo_stuff()
    sys.argv.remove("--foo")
...
setup(..)

有关如何使用distutils执行此操作的文档非常糟糕,最终我遇到了这个问题:搭便车指导包装,使用sdist和使用它user_options.我发现扩展的distutils参考不是特别有用.

虽然这看起来像是使用distutils的"正确"方式(至少是我能找到的唯一一个模糊记录的方法).我在其他答案中找不到任何东西--with--without开关.

这种distutils解决方案的问题在于它只是涉及我正在寻找的东西(这也可能是你的情况).添加几十行和子类化sdist对我来说是错误的.


这个解决方案不正确,因为--foo可能用于另一个命令:使用"setup.py build_ext --inplace --foo install",安装不应该认为它有--foo.
我不知道你为什么要给我一个我希望能做的例子.我从未声称这是一个解决方案,为什么说这不正确?我提供了关于这个主题的唯一文档的指示,说它"不像通常认为的那么难"不能帮助我们找到更好的答案.

3> Ronen Botzer..:

是的,它是2015年在这两个添加命令和选项的文件setuptools,并distutils在很大程度上仍然下落不明.

经过几个令人沮丧的时间后,我想出了以下代码,用于为以下install命令添加自定义选项setup.py:

from setuptools.command.install import install


class InstallCommand(install):
    user_options = install.user_options + [
        ('custom_option=', None, 'Path to something')
    ]

    def initialize_options(self):
        install.initialize_options(self)
        self.custom_option = None

    def finalize_options(self):
        #print('The custom option for install is ', self.custom_option)
        install.finalize_options(self)

    def run(self):
        global my_custom_option
        my_custom_option = self.custom_option
        install.run(self)  # OR: install.do_egg_install(self)

值得一提的是,install.run()会检查它是"本机"调用还是已修补:

if not self._called_from_setup(inspect.currentframe()):
    orig.install.run(self)
else:
    self.do_egg_install()

此时,您可以使用以下命令注册命令setup:

setup(
    cmdclass={
        'install': InstallCommand,
    },
    :



4> Armin Ronach..:

您无法将自定义参数传递给脚本.但是,以下事情是可能的,可以解决您的问题:

可以使用可选功能--with-featurename,可以禁用标准功能--without-featurename.[AFAIR这需要setuptools]

你可以使用环境变量,但这些变量需要set在windows上,而前缀可以在linux/OS X(FOO=bar python setup.py)上使用.

您可以使用自己的cmd_classes 扩展distutils,这可以实现新功能.它们也是可链接的,因此您可以使用它来更改脚本中的变量.(python setup.py foo install)将在foo执行之前执行该命令install.

希望有所帮助.一般来说,我建议提供更多信息,确切地说您的额外参数应该做什么,也许有更好的解决方案可用.



5> 小智..:

也许您像我一样是一个没有经验的程序员,但在阅读完以上所有答案后仍然感到吃力。因此,您可能会发现另一个可能有用的示例(并解决了前面有关输入命令行参数的答案中的注释):

class RunClientCommand(Command):
    """
    A command class to runs the client GUI.
    """

    description = "runs client gui"

    # The format is (long option, short option, description).
    user_options = [
        ('socket=', None, 'The socket of the server to connect (e.g. '127.0.0.1:8000')',
    ]

    def initialize_options(self):
        """
        Sets the default value for the server socket.

        The method is responsible for setting default values for
        all the options that the command supports.

        Option dependencies should not be set here.
        """
        self.socket = '127.0.0.1:8000'

    def finalize_options(self):
        """
        Overriding a required abstract method.

        The method is responsible for setting and checking the 
        final values and option dependencies for all the options 
        just before the method run is executed.

        In practice, this is where the values are assigned and verified.
        """
        pass

    def run(self):
        """
        Semantically, runs 'python src/client/view.py SERVER_SOCKET' on the
        command line.
        """
        print(self.socket)
        errno = subprocess.call([sys.executable, 'src/client/view.py ' + self.socket])
        if errno != 0:
            raise SystemExit("Unable to run client GUI!")

setup(
    # Some other omitted details
    cmdclass={
        'runClient': RunClientCommand,
    },

上面的代码已经过测试,并且是我编写的一些代码。我还提供了一些更详细的文档字符串,以使事情更容易理解。

至于命令行:python setup.py runClient --socket=127.0.0.1:7777。使用print语句进行的快速仔细检查表明,run方法确实选择了正确的参数。

其他资源,我发现有用的(更多更多的例子):

自定义distutils命令

https://seasonofcode.com/posts/how-to-add-custom-build-steps-and-commands-to-setuppy.html

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有