【问题标题】:How to obtain arguments passed to setup.py from pip with '--install-option'?如何使用“--install-option”从 pip 获取传递给 setup.py 的参数?
【发布时间】:2013-09-14 12:43:27
【问题描述】:

我正在使用 pip 1.4.1,尝试从本地路径安装包,例如:

pip install /path/to/my/local/package

这就是我想要的,这或多或少相当于运行python /path/to/my/local/package/setup.py install,但我想将一些额外的选项/参数传递给我的包的 setup.py 安装。

我了解from the pip documentation 可以使用--install-option 选项,例如:

pip install --install-option="--some-option" /path/to/my/local/package

python-virtualenv Google Group 的This post 建议这是可能的。

我不明白的是如何从 setup.py 中获取传入的“--some-option”。我尝试查看sys.argv,但无论我为“--install-option =”添加什么,sys.argv 总是这样:

['-c', 'egg_info', '--egg-base', 'pip-egg-info']

如何从 pip install 获取作为“--install-option”传入的东西的值?

【问题讨论】:

  • 抱歉新手问题。你是如何打印sys.argv 来获得['-c', 'egg_info', '--egg-base', 'pip-egg-info'] 的?我正在尝试打印它以调试我的 setup.py。
  • 嘿...已经有一段时间了,但我想我可能只是在setup.py 中做了import sys 然后print(sys.argv)
  • 谢谢它有效。只是因为执行命令有很多输出,所以我的打印被埋在了输出中。

标签: python pip setuptools


【解决方案1】:

我在安装 pyside 时遇到了这个问题。

我需要指定--qmake 选项。

这是您需要的表格:

pip install --install-option="--qmake=/usr/lib64/qt4/bin/qmake" PySide

【讨论】:

  • 感谢您的回答。我已经把它放在一边,因为我不久前找到了解决这个问题的其他方法,但我会试试看。我记得,我认为它不起作用。安装本地软件包与安装 PyPI 软件包之间存在一些差异,但我可能弄错了。
  • 此选项--qmake与项目PySide相关。要添加自定义选项,您需要注册setuptools.command.install(和/或.develop)的派生类来管理它(如上面的答案中所述)。
【解决方案2】:

您需要使用自己的自定义命令扩展安装命令。在run 方法中,您可以将选项的值公开给setup.py(在我的示例中,我使用全局变量)。

from setuptools.command.install import install


class InstallCommand(install):
    user_options = install.user_options + [
        ('someopt', None, None), # a 'flag' option
        #('someval=', None, None) # an option that takes a value
    ]

    def initialize_options(self):
        install.initialize_options(self)
        self.someopt = None
        #self.someval = None

    def finalize_options(self):
        #print("value of someopt is", self.someopt)
        install.finalize_options(self)

    def run(self):
        global someopt
        someopt = self.someopt # will be 1 or None
        install.run(self)

使用setup 函数注册自定义安装命令。

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

看来你的论点顺序不对

pip install /path/to/my/local/package --install-option="--someopt"

【讨论】:

  • 顺便说一下,一旦您将安装命令子类化,您应该能够在sys.argv 上看到那些。
  • 只是为了澄清一下,在 setup(...) 中,您将如何使用 cmdclass 技术访问您传入的变量?
  • cmdclass 设置有一个选项(完全)。没有它 pip 会抱怨并且不执行操作。它会将其传递给 setup.py,您可以在其中检查 sys.argv 中的选项值。
  • 顺便说一句,在user_options 中使用下划线似乎是被禁止的:distutils.errors.DistutilsGetoptError: invalid long option name 'some_option' (must be letters, numbers, hyphens only 对,我正在尝试使用此代码的注释掉的“some_val”版本并以error: option --someval not recognised 结尾.尽管python setup.py install -h 表明新标志已被识别,但事实仍然如此。
  • 这根本行不通,pip 摄取选项并将它们发送到 /dev/null :(
【解决方案3】:

效果很好,documented.

from setuptools.command.install import install

class InstallCommand(install):             
    user_options = install.user_options + [
        ('engine=', None, '<description for this custom option>'),
    ]                                      

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

    def finalize_options(self):                   
        print("value of engine is", self.engine)
        install.finalize_options(self)            

    def run(self):                                
        print(self.engine)                       
        install.run(self)                         

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

一个常见的错误是将setup 选项传递给pip,就像你将它直接传递给setup 一样。 像这样使用 pip 中的选项:

pip install . --install-option="--engine=rabbitmq"

但是这种方式是错误的方式:

pip install . --install-option="--engine rabbitmq"

没有等号会导致众所周知的错误:

错误:选项 --engines rabbitmq 无法识别

【讨论】:

    【解决方案4】:

    为了保持一致性,您可以为 setup.py installsetup.py develop(又名 pip install -e)添加一个选项:(基于 Ronen Botzer 的回答)

    from setuptools import setup
    from setuptools.command.install import install
    from setuptools.command.develop import develop
    
    
    class CommandMixin(object):
        user_options = [
            ('someopt', None, 'a flag option'),
            ('someval=', None, 'an option that takes a value')
        ]
    
        def initialize_options(self):
            super().initialize_options()
            # Initialize options
            self.someopt = None
            self.someval = 0
    
        def finalize_options(self):
            # Validate options
            if self.someval < 0:
                raise ValueError("Illegal someval!")
            super().finalize_options()
    
        def run(self):
            # Use options
            global someopt
            someopt = self.someopt # will be 1 or None
    
            super().run()
    
    class InstallCommand(CommandMixin, install):
        user_options = getattr(install, 'user_options', []) + CommandMixin.user_options
    
    class DevelopCommand(CommandMixin, develop):
        user_options = getattr(develop, 'user_options', []) + CommandMixin.user_options
    
    setup(
        ...,
        cmdclass={
            'install': InstallCommand,
            'develop': DevelopCommand,
        }
    

    然后您可以将选项传递给 pip,例如:

    pip install --install-option="--someval=1" --install-option="--someopt" .
    

    或处于开发模式:

    pip install -e --install-option="--someval=1" .
    

    【讨论】:

    • 我想发送 include_dirs 和 library_dirs 来构建我的模块,之前我会在 setup() 中填充 include_dirs 和 library_dirs,我现在应该如何处理?
    • @Rika 不要通过 install 命令执行此操作。而是看stackoverflow.com/q/51522248/81658
    【解决方案5】:

    在此great anwser 之上。 还有一点需要注意的是--install-options 不是work with wheel

    从 7.0 版开始,pip 支持通过需求文件控制提供给 setup.py 的命令行选项。这会禁用该软件包的轮子(缓存或其他方式),因为轮子不存在 setup.py。

    但是,当你使用setup.py 构建轮子时,你可以使用

    python setup.py bdist_wheel install -your-options
    

    自定义安装阶段,这会影响到wheel包的.dist-info

    【讨论】:

      猜你喜欢
      • 2018-04-22
      • 1970-01-01
      • 1970-01-01
      • 2010-10-15
      • 2013-03-21
      • 2020-04-07
      • 2018-09-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多