请提示我如何将命令行和setup.cfg配置文件中的用户定义参数传递给distutils的setup.py脚本.我想编写一个setup.py脚本,它接受我的包特定参数.例如:
python setup.py install -foo myfoo
Run Code Online (Sandbox Code Playgroud)
谢谢你,
Mher
Cer*_*rin 59
由于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,
}
)
Run Code Online (Sandbox Code Playgroud)
tot*_*aam 26
这是一个非常简单的解决方案,您需要做的就是sys.argv
在调用distutils之前过滤掉并自己处理它setup(..)
.像这样的东西:
if "--foo" in sys.argv:
do_foo_stuff()
sys.argv.remove("--foo")
...
setup(..)
Run Code Online (Sandbox Code Playgroud)
有关如何使用distutils执行此操作的文档非常糟糕,最终我遇到了这个问题:搭便车指导包装,使用sdist
和使用它user_options
.我发现扩展的distutils参考不是特别有用.
虽然这看起来像是使用distutils的"正确"方式(至少是我能找到的唯一一个模糊记录的方法).我在其他答案中找不到任何东西--with
和--without
开关.
这种distutils解决方案的问题在于它只是涉及我正在寻找的东西(这也可能是你的情况).添加几十行和子类化sdist
对我来说是错误的.
Ron*_*zer 16
是的,它是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)
Run Code Online (Sandbox Code Playgroud)
值得一提的是,install.run()会检查它是"本机"调用还是已修补:
if not self._called_from_setup(inspect.currentframe()):
orig.install.run(self)
else:
self.do_egg_install()
Run Code Online (Sandbox Code Playgroud)
此时,您可以使用以下命令注册命令setup
:
setup(
cmdclass={
'install': InstallCommand,
},
:
Run Code Online (Sandbox Code Playgroud)
Arm*_*her 11
您无法将自定义参数传递给脚本.但是,以下事情是可能的,可以解决您的问题:
--with-featurename
,可以禁用标准功能--without-featurename
.[AFAIR这需要setuptools]set
在windows上,而前缀可以在linux/OS X(FOO=bar python setup.py
)上使用.cmd_class
es 扩展distutils,这可以实现新功能.它们也是可链接的,因此您可以使用它来更改脚本中的变量.(python setup.py foo install
)将在foo
执行之前执行该命令install
.希望有所帮助.一般来说,我建议提供更多信息,确切地说您的额外参数应该做什么,也许有更好的解决方案可用.
小智 9
我成功地使用了一种解决方法来使用类似于 totaam 建议的解决方案。我最终从 sys.argv 列表中弹出了我的额外参数:
import sys
from distutils.core import setup
foo = 0
if '--foo' in sys.argv:
index = sys.argv.index('--foo')
sys.argv.pop(index) # Removes the '--foo'
foo = sys.argv.pop(index) # Returns the element after the '--foo'
# The foo is now ready to use for the setup
setup(...)
Run Code Online (Sandbox Code Playgroud)
可以添加一些额外的验证以确保输入良好,但这就是我所做的
与 totaam 给出的类似的快速简单的方法是使用 argparse 来获取 -foo 参数,并将其余参数留给 distutils.setup() 的调用。恕我直言,为此使用 argparse 比手动迭代 sys.argv 更好。例如,将其添加到 setup.py 的开头:
argparser = argparse.ArgumentParser(add_help=False)
argparser.add_argument('--foo', help='required foo argument', required=True)
args, unknown = argparser.parse_known_args()
sys.argv = [sys.argv[0]] + unknown
Run Code Online (Sandbox Code Playgroud)
该add_help=False
参数意味着您仍然可以使用常规 setup.py 帮助-h
(前提--foo
是给出)。
也许您像我一样是一个没有经验的程序员,但在阅读完以上所有答案后仍然感到吃力。因此,您可能会发现另一个可能有用的示例(并解决了前面有关输入命令行参数的答案中的注释):
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!")
Run Code Online (Sandbox Code Playgroud)
setup(
# Some other omitted details
cmdclass={
'runClient': RunClientCommand,
},
Run Code Online (Sandbox Code Playgroud)
上面的代码已经过测试,并且是我编写的一些代码。我还提供了一些更详细的文档字符串,以使事情更容易理解。
至于命令行:python setup.py runClient --socket=127.0.0.1:7777
。使用print语句进行的快速仔细检查表明,run方法确实选择了正确的参数。
其他资源,我发现有用的(更多和更多的例子):
https://seasonofcode.com/posts/how-to-add-custom-build-steps-and-commands-to-setuppy.html
为了与两者完全兼容,python setup.py install
您pip install .
需要使用环境变量,因为pip
选项--install-option=
有问题:
这是一个不使用以下内容的完整示例--install-option
:
import os
environment_variable_name = 'MY_ENVIRONMENT_VARIABLE'
environment_variable_value = os.environ.get( environment_variable_name, None )
if environment_variable_value is not None:
sys.stderr.write( "Using '%s=%s' environment variable!\n" % (
environment_variable_name, environment_variable_value ) )
setup(
name = 'packagename',
version = '1.0.0',
...
)
Run Code Online (Sandbox Code Playgroud)
然后,你可以在 Linux 上像这样运行它:
MY_ENVIRONMENT_VARIABLE=1 pip install .
MY_ENVIRONMENT_VARIABLE=1 pip install -e .
MY_ENVIRONMENT_VARIABLE=1 python setup.py install
MY_ENVIRONMENT_VARIABLE=1 python setup.py develop
Run Code Online (Sandbox Code Playgroud)
但是,如果您使用的是 Windows,请像这样运行:
set "MY_ENVIRONMENT_VARIABLE=1" && pip install .
set "MY_ENVIRONMENT_VARIABLE=1" && pip install -e .
set "MY_ENVIRONMENT_VARIABLE=1" && python setup.py install
set "MY_ENVIRONMENT_VARIABLE=1" && python setup.py develop
Run Code Online (Sandbox Code Playgroud)
参考:
归档时间: |
|
查看次数: |
27723 次 |
最近记录: |