argparse
に小さな問題があります。プロットのxlim
であるオプションxrange
があります。 -2e-5
のような番号を渡せるようにしたい。ただし、これは機能しません-argparse
は、これが位置引数であると解釈します。 -0.00002
を実行すると、機能します。argparse
はそれを負の数として読み取ります。 -2e-3
を読み取ることはできますか?
コードは以下のとおりです。実行方法の例は次のとおりです。
./blaa.py --xlim -2.e-3 1e4
私が以下を行う場合、それは機能します:
./blaa.py --xlim -0.002 1e4
コード:
parser.add_argument('--xlim', nargs = 2,
help = 'X axis limits',
action = 'store', type = float,
default = [-1.e-3, 1.e-3])
このように機能させることはできますが、実際には科学的記数法を使用できるようにしたいと思います。誰かアイデアはありますか?
乾杯
コメントですでに指摘されているように、問題は、-
プレフィックスが引数ではなくオプションとして解析されることです。これを回避する1つの方法は、オプションに使用されるプレフィックスを prefix_chars
引数で変更することです。
#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser(prefix_chars='@')
parser.add_argument('@@xlim', nargs = 2,
help = 'X axis limits',
action = 'store', type = float,
default = [-1.e-3, 1.e-3])
print parser.parse_args()
出力例:
$ ./blaa.py @@xlim -2.e-3 1e4
Namespace(xlim=[-0.002, 10000.0])
編集:または、-
を区切り文字として使用し続け、xlim
を単一の値として渡し、type
の関数を使用して独自の解析を実装することもできます。
#!/usr/bin/python
import argparse
def two_floats(value):
values = value.split()
if len(values) != 2:
raise argparse.ArgumentError
values = map(float, values)
return values
parser = argparse.ArgumentParser()
parser.add_argument('--xlim',
help = 'X axis limits',
action = 'store', type=two_floats,
default = [-1.e-3, 1.e-3])
print parser.parse_args()
出力例:
$ ./blaa.py --xlim "-2e-3 1e4"
Namespace(xlim=[-0.002, 10000.0])
私が見つけた回避策の1つは、値を引用することですが、スペースを追加します。あれは、
./blaa.py --xlim " -2.e-3" 1e4
このように、argparseは、最初の文字がハイフンダッシュではないため、-2.e-3がオプション名であるとは見なしませんが、float(string)は左側のスペースを無視するため、floatに適切に変換されます。
別の回避策は、引数を引用することに加えて、「=
」記号を使用して引数を渡すことです-つまり、--xlim="-2.3e14"
これが私が使用するコードです。 (これはjeremiahbuddhaのものと似ていますが、負の数を扱うため、質問に直接答えます。)
argparse.ArgumentParser()
を呼び出す前にこれを置いてください
for i, arg in enumerate(sys.argv):
if (arg[0] == '-') and arg[1].isdigit(): sys.argv[i] = ' ' + arg
オプションの値を等号で指定すると、-
で始まっていても、argparse
はそれを個別のオプションとして扱いません。
./blaa.py --xlim='-0.002 1e4'
# As opposed to --xlim '-0.002 1e4'
また、値にスペースが含まれていない場合は、引用符を削除できます。
./blaa.py --xlim=-0.002
参照: https://www.gnu.org/software/guile/manual/html_node/Command-Line-Format.html
これにより、受け入れられた回答が示すように、独自のtype=
パーサーを記述したり、プレフィックス文字を-
から@
に再定義したりする必要はありません。
_argparse.py
_自体を変更する場合は、負の数のマッチャーを変更して科学的記数法を処理できます。
class _ActionsContainer.__init__()
で
_self._negative_number_matcher = _re.compile(r'^-(\d+\.?|\d*\.\d+)([eE][+\-]?\d+)?$')
_
または、パーサーを作成した後、_parser._negative_number_matcher
_をこの値に設定できます。このアプローチは、グループまたはサブパーサーを作成している場合に問題が発生する可能性がありますが、単純なパーサーで機能するはずです。
Andrewfnのアプローチに触発されて、私はsys.argv
をいじる別のヘルパー関数を作成しました。
def _Tweak_neg_scinot():
import re
import sys
p = re.compile('-\\d*\\.?\\d*e', re.I)
sys.argv = [' ' + a if p.match(a) else a for a in sys.argv]
正規表現は以下を探します:
-
:負の符号\\d*
:0桁以上(-.5e-2
や-4354.5e-6
などの奇妙な形式の値の場合)\\.?
:オプションの期間(例:-2e-5
は妥当です)\\d*
:0桁以上の別のセット(-2e-5
や-7.e-3
などの場合)e
:指数マーカーと一致させるre.I
は、-2e-5
と-2E-5
の両方に一致します。 p.match
を使用すると、各文字列の先頭からのみ検索されます。