2017-10-10 12 views
0

私はPython 2.7を使用しており、argparseを使用してシェルのような動作を実現しようとしています。 私の問題は、Python 2.7では、argparseのサブパーザをオプションとして使用する方法を見つけることができないということです。 私の問題を説明するのは難しいですから、私のプログラムから必要なものを説明します。Python 2.7でArgparseモジュールを使用してデフォルトサブパーザを設定する方法

プログラムは仕事の2つのモードがあります:指定されたコマンドとプログラム(各コマンドはそれ自身の 追加の引数を持っている)と追加の引数を開始

  1. は、特定の タスクを実行します。
  2. コマンドを使わないでプログラムを起動すると、シェルのようなプログラムが起動します。このプログラムは、引数の行をとり、与えられた行を引数として プログラムが呼び出されたかのように処理します。だから、

例えば私のプログラムは、 'CMD1' と 'CMD2' コマンドをサポートしている場合、私はそうのようにそれを使用することができます。

  • python program.py cmd1 additional_args1
  • python program.py cmd2 additional_args2

またはシェルとモード:

  • また
    • cmd1 additional_args1
    • cmd2 additional_args2
    • quit

、私はまた、私のプログラムは、すべてのコマンドに影響しますオプションのグローバル引数を取ることができるようにしたいです。そのために

私は(これは純粋な例である)ので、同じようargparse使用しています:

parser = argparse.ArgumentParser(description="{} - Version {}".format(PROGRAM_NAME, PROGRAM_VERSION)) 

parser.add_argument("-i", "--info", help="Display more information") 

subparsers = parser.add_subparsers() 

parserCmd1 = subparsers.add_parser("cmd1", help="First Command") 
parserCmd1.set_defaults(func=cmd1) 

parserCmd2 = subparsers.add_parser("cmd2", help="Second Command") 
parserCmd2.add_argument("-o", "--output", help="Redirect Output") 
parserCmd2.set_defaults(func=cmd2) 

だから私は(または-oフラグなし)(なし、追加の引数を持つ)CMD1またはCMD2を呼び出すことができます。両方の場合、呼び出されたコマンドのさらに多くの情報を表示するためにフラグ-iを追加することができます。

私は、引数としてCMD1またはCMD2を提供する必要があるため私の問題は、(理由は必須ですsubparsersを使用する)、私はシェルモードを有効にすることができないことを

制限事項です:私は、Pythonを使用することはできません

  • 3(簡単にそこで実行できることはわかっています)
  • グローバルなオプション引数のため、引数の解析をスキップする引数がないかどうかを確認することはできません。
  • 私はそれが、どのように私はargparseとPython 2.7でのこのような行為を達成することができ、すべての

で何のコマンドを提供していないしなければならない場合、シェルを呼び出すための新しいコマンドを追加したくありませんか?

+0

だけで簡単なメモ - subparsersがオプションであるという事実は、バグです。彼らは必要とされていましたが(通常のポジションと同じですが)、数年前の無関係の変更では、サブパーザーがクラックを通過しました。 – hpaulj

答えて

1

もう1つのアイデアは、2段階の解析を使用することです。一つは 'グローバル'を扱い、それは扱えない文字列を返します。次に、条件付きでサブパーザを使って補足を処理します。

import argparse 

def cmd1(args): 
    print('cmd1', args) 
def cmd2(args): 
    print('cmd2', args) 

parser1 = argparse.ArgumentParser() 

parser1.add_argument("-i", "--info", help="Display more information") 

parser2 = argparse.ArgumentParser() 
subparsers = parser2.add_subparsers(dest='cmd') 

parserCmd1 = subparsers.add_parser("cmd1", help="First Command") 
parserCmd1.set_defaults(func=cmd1) 

parserCmd2 = subparsers.add_parser("cmd2", help="Second Command") 
parserCmd2.add_argument("-o", "--output", help="Redirect Output") 
parserCmd2.set_defaults(func=cmd2) 

args, extras = parser1.parse_known_args() 
if len(extras)>0 and extras[0] in ['cmd1','cmd2']: 
    args = parser2.parse_args(extras, namespace=args) 
    args.func(args) 
else: 
    print('doing system with', args, extras) 

サンプルの実行:

0901:~/mypy$ python stack46667843.py -i info 
('doing system with', Namespace(info='info'), []) 
0901:~/mypy$ python stack46667843.py -i info extras for sys 
('doing system with', Namespace(info='info'), ['extras', 'for', 'sys']) 
0901:~/mypy$ python stack46667843.py -i info cmd1 
('cmd1', Namespace(cmd='cmd1', func=<function cmd1 at 0xb74b025c>, info='info')) 
0901:~/mypy$ python stack46667843.py -i info cmd2 -o out 
('cmd2', Namespace(cmd='cmd2', func=<function cmd2 at 0xb719ebc4>, info='info', output='out')) 
0901:~/mypy$ 
+0

返事をお寄せいただきありがとうございます。必要です。 – Yoavhayun

1

「オプションの」サブパートのトピックに関するバグ/問題(リンクあり)。

https://bugs.python.org/issue29298

これは、最近のプルリクエストを持っていることに注意してください。あなたのスクリプトと

args = parser.parse_args() 
print(args) 

結果は

1008:~/mypy$ python3 stack46667843.py 
Namespace(info=None) 
1009:~/mypy$ python2 stack46667843.py 
usage: stack46667843.py [-h] [-i INFO] {cmd1,cmd2} ... 
stack46667843.py: error: too few arguments 
1009:~/mypy$ python2 stack46667843.py cmd1 
Namespace(func=<function cmd1 at 0xb748825c>, info=None) 
1011:~/mypy$ python3 stack46667843.py cmd1 
Namespace(func=<function cmd1 at 0xb7134dac>, info=None) 

いるの追加により


私は 'オプション' subparsersはPY2と3つの両方のバージョンに影響を与えたと思ったが、どうやらそうではありません。理由を検証するためにコードを調べる必要があります。両方の言語で


subparsers.requiredFalseです。私は本当の

subparsers.required=True 

(とsubparsers定義にdestを追加)に設定すると、PY3エラーメッセージが

1031:~/mypy$ python3 stack46667843.py 
usage: stack46667843.py [-h] [-i INFO] {cmd1,cmd2} ... 
stack46667843.py: error: the following arguments are required: cmd 

あるのでrequired引数にどのように2つのバージョンのテストに差があります。 Py3はrequired属性に注意を払います。 Py2(明らかに)は、positionalsのリストが空であるかどうかをチェックする以前の方法を使用します。


parser._parse_known_argsの末尾付近で必要な引数が確認されます。

Python2.7はaction.requiredをチェック反復前

# if we didn't use all the Positional objects, there were too few 
    # arg strings supplied. 
    if positionals: 
     self.error(_('too few arguments')) 

を含みます。これは、不足しているものを捕まえてcmdといい、too few argumentsと言っています。

したがって、kludgeはargparse.pyを編集し、そのブロックを削除してPy3バージョンの対応するセクションに一致させることです。

+0

こんにちは、応答をありがとう、また私はPython3を使用することはできません同じ理由で、argparseを編集することはできません、私はPython3との違いがあると思う理由を理解するためにあなたの質問をより詳細に調べる必要があります。これは私が働いている会社の人々が使用するツールになるでしょう。私が持っている唯一の保証はPython 2.7がインストールされていることです。 – Yoavhayun

関連する問題