コマンドラインとsetup.cfg構成ファイルの両方からユーザー定義パラメーターをdistutilsのsetup.pyスクリプトに渡す方法を教えてください。パッケージ固有のパラメーターを受け入れるsetup.pyスクリプトを書きたいのですが。例えば:
python setup.py install -foo myfoo
ありがとうございました、
Setuptools/Distuilsがひどく文書化されているので、自分でこれに対する答えを見つけるのに問題がありました。しかし、最終的には this の例に出くわしました。また、 this 同様の質問が役に立ちました。基本的に、オプション付きのカスタムコマンドは次のようになります。
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,
}
)
これは非常にシンプルなソリューションです。_sys.argv
_をフィルターで取り除き、distutils setup(..)
を呼び出す前に自分で処理するだけです。このようなもの:
_if "--foo" in sys.argv:
do_foo_stuff()
sys.argv.remove("--foo")
...
setup(..)
_
Distutilsでこれを行う方法に関するドキュメントはひどいものですが、最終的に私はこれに遭遇しました: ヒッチハイカーのパッケージ化ガイド 、sdist
とその_user_options
_を使用します。 extending distutils の参照は特に役に立ちません。
これは、distutilsでそれを行う「適切な」方法のように見えますが(少なくとも、漠然と文書化されている唯一の方法です)。他の回答に記載されている_--with
_および_--without
_スイッチには何も見つかりませんでした。
このdistutilsソリューションの問題は、私が探しているものにはあまりにも複雑すぎることです(これはあなたにも当てはまる場合があります)。何十行も追加してsdist
をサブクラス化するのは私にとっては間違っています。
はい、それは2015年であり、setuptools
とdistutils
の両方にコマンドとオプションを追加するためのドキュメントはまだほとんどありません。
イライラする数時間後、setup.py
のinstall
コマンドにカスタムオプションを追加するための次のコードを見つけました。
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,
},
:
スクリプトにカスタムパラメータを渡すことはできません。ただし、次のことが可能であり、問題を解決できる可能性があります。
--with-featurename
を使用して有効にでき、標準機能は--without-featurename
を使用して無効にできます。 [これにはsetuptoolsが必要です]set
である必要がありますが、Linux/OS X(FOO=bar python setup.py
)では接頭辞が付きます。cmd_class
esでdistutilsを拡張できます。それらは連鎖可能でもあるので、それを使用してスクリプト内の変数を変更できます。 (python setup.py foo install
)は、foo
を実行する前にinstall
コマンドを実行します。何とかお役に立てば幸いです。一般的に言って、追加のパラメーターが正確に何をすべきかについて、もう少し情報を提供することをお勧めします。
おそらく、あなたは上記のようなすべての答えを読んだ後もまだ苦労している私のような無作法なプログラマーです。したがって、別の例が役立つ可能性があります(およびコマンドライン引数の入力に関する以前の回答のコメント):
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,
},
上記は私が書いたいくつかのコードからテストされています。わかりやすくするために、もう少し詳細なdocstringも含めました。
コマンドラインの場合:python setup.py runClient --socket=127.0.0.1:7777
。 printステートメントを使用した簡単なダブルチェックは、runメソッドによって実際に正しい引数が取得されていることを示しています。
その他の役立つリソース(moreおよびmore例):
https://seasonofcode.com/posts/how-to-add-custom-build-steps-and-commands-to-setuppy.html
私は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(...)
入力が適切であることを確認するために追加の検証を追加できますが、これは私が行った方法です
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
add_help=False
引数は、-h
を使用して通常のsetup.pyヘルプを引き続き取得できることを意味します(--foo
が指定されている場合)。
pip
オプションpython setup.py install
にはバグがあるため、pip install .
と--install-option=
の両方と完全に互換性を保つには、環境変数を使用する必要があります。
--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',
...
)
その後、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
ただし、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
参照: