How to obtain arguments passed to setup.py from pi

2019-01-15 07:43发布

I am using pip 1.4.1, attempting to install a package from a local path, for example:

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

This does what I want, which is more or less the equivalent of running python /path/to/my/local/package/setup.py install, but I would like to pass some additional options/arguments to my package's setup.py install.

I understand from the pip documentation that this is possible with the --install-option option, for example:

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

This post from the python-virtualenv Google Group suggests this is possible.

What I do not understand is how to obtain the passed-in "--some-option" from within setup.py. I tried looking at sys.argv, but no matter what I put for "--install-option=", sys.argv is always this:

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

How can I get the values of things passed in as "--install-option" from pip install?

4条回答
Viruses.
2楼-- · 2019-01-15 07:52

You need to extend the install command with a custom command of your own. In the run method you can expose the value of the option to setup.py (in my example I use a global variable).

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)

Register the custom install command with the setup function.

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

It seems that the order of your arguments is off

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

查看更多
【Aperson】
3楼-- · 2019-01-15 08:03

It works well and also 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}
...
)

One of common mistakes is to pass setup options to pip like you pass it to setup directly. Use options from pip like that:

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

But this way is a wrong way:

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

Absence of equal sign causes well known error:

error: option --engines rabbitmq not recognized

查看更多
Fickle 薄情
4楼-- · 2019-01-15 08:05

I was having this problem installing pyside.

I needed to specify the --qmake option.

This is the form you need:

pip install --install-option="--qmake=/usr/lib64/qt4/bin/qmake" PySide
查看更多
看我几分像从前
5楼-- · 2019-01-15 08:08

For consistency, you can add an option to both setup.py install and setup.py develop (aka pip install -e): (building off Ronen Botzer's answer)

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(self)
        # 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(self)

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

        super().run(self)

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,
    }

Then you can pass options to pip like:

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

Or in develop mode:

pip install -e --install-option="--someval=1" .
查看更多
登录 后发表回答