将命令行参数传递给pip install

时间:2017-11-09 19:29:59

标签: python pip setup.py

我目前正在开发一个导入Fortran模块的Python项目。 setup.py看起来与

相似
from numpy.distutils.core import Extension
from numpy.distutils.core import setup

ext = Extension(
    name = "fortran_module",
    sources = ["fortran_module.f90"],
    extra_f90_compile_args = ["-some -compile -arguments"]
)

setup(
    ...,
    ...,
    ...,
    ext_modules = [ext],
    ...,
    ...,
    ...
)

我目前正在使用pip install -e .进行安装,效果很好。 但有时我需要更改extra_f90_compile_args并且我希望在使用pip安装期间将它们作为命令行参数给出,而不是更改setup.py文件。像这样的东西:

pip install -e --compile_args="-O3 -fbacktrace -fbounds-check -fopenmp" .

是否可以通过pip将命令行参数传递到setup.py文件中?

与此相关,我还想将不同的设置选项传递到setup.py。例如

pip install -e --setup=setup1 .

pip install -e --setup=setup2 .

根据setup1setup2或者没有传递它们,我想包含不同的Fortran源文件,并使用不同的extra_f90_compile_args编译它们。

这可能吗?

编辑:让我们考虑以下示例:Fortran模块与OpenMP并行化。现在我希望用户决定是否编译并行。也许OpenMP库不可用,用户需要编译串行版本。

我的setup.py现在看起来如下

from numpy.distutils.core import Extension
from numpy.distutils.core import setup
import os
from setuptools.command.install import install as _install

extra_f90_compile_args = ""
extra_link_args = ""

class install(_install):
    user_options = _install.user_options + [('build=', None, None)]

    def initialize_options(self):
        _install.initialize_options(self)
        self.build = None

    def finalize_options(self):
        _install.finalize_options(self)

    def run(self):
        global extra_f90_compile_args
        global extra_link_args
        if(self.build == "parallel"):
            extra_f90_compile_args += "-fopenmp"
            extra_link_args += "-lgomp"
            os.makedirs("~/test/")
        _install.run(self)

ext = Extension(
    name="test_module.fortran_module",
    sources=["test_module/fortran_module.f90"],
    extra_f90_compile_args=[extra_f90_compile_args],
    extra_link_args=[extra_link_args]
)

setup(
    name="test_module",
    packages=["test_module"],
    ext_modules=[ext],
    cmdclass={'install': install}
)

如果我用

安装它
pip install . --install-option="--build=parallel"

它正在if - 块中执行代码。我创建了test/目录只是为了检查这个。如果build未与parallel给出或不同,则不会创建test/目录。

但是,代码不是使用OpenMP编译的。我认为这是因为Extension对象是在调用setup()之前创建的,其中参数得到评估。我想首先评估参数,然后根据参数创建Extension对象,然后调用setup()

我该怎么做?

2 个答案:

答案 0 :(得分:2)

在深入挖掘源代码后,我现在可以回答这个问题了。

setup.py文件:

from numpy.distutils.command.install import install as _install
from numpy.distutils.core import Extension
from numpy.distutils.core import setup

extF = Extension(name="test_module.fortran_module",
                 sources=["test_module/fortran_module.f90"])
compile_args_parallel = "-fopenmp"
link_args_parallel = "-lgomp"

class install(_install):
    user_options = _install.user_options + [('build=', None, None)]

    def initialize_options(self):
        _install.initialize_options(self)
        self.build = None

    def finalize_options(self):
        _install.finalize_options(self)
        if(self.build == "parallel"):
            for ext in self.distribution.ext_modules:
                if(ext.name == "test_module.fortran_module"):
                    ext.extra_f90_compile_args = compile_args_parallel
                    ext.extra_link_args = link_args_parallel

    def run(self):
        _install.run(self)

setup(
    name="test_module",
    packages=["test_module"],
    ext_modules=[extF],
    cmdclass={"install": install}
)

使用

安装
pip install .

安装串行版本和

pip install . --install-option="--build=parallel"

安装Fortran模块的并行版本。

答案 1 :(得分:0)

如果我认为有多个选择,那么--install-option--global-option的交易似乎很混乱。我想添加this real life solution

取而代之的是环境变量,并在安装时进行设置。

在setup.py中:

import os
config_var = os.environ.get("MY_PARAM", None)
if config_var:
    do_something()
setup()

,然后像这样呼叫点: MY_PARAM="Some_value" pip install my_module

相关问题