2012-04-09 33 views
6

optparseからargparseに切り替えた後、私は奇妙なエラーが発生しています。Python:optparseからargparseに切り替える

myScript.py -oOpt 

または等号置く:Argparse空白が生じない場合にのみ、引数を解析

myScript.py -o=Opt 

をし、それが通常のように動作しません:

myScript.py -o Opt 

はここに私のargparseの初期化です:

#!/usr/bin/env python 
# to get description use the -h flag 

import argparse, os, sys 


# ====================== 
# Python2.7 is expected: 

if sys.version_info[0] != 2 or sys.version_info[1] < 7: 
    sys.exit('This program needs Python2.7+') 


# ========== 
# preambule: 

desc = """Enter dirs in the current dir and makes gro out of state.cpt there.""" 
# parser = argparse.ArgumentParser() 
parser = argparse.ArgumentParser(description=desc, version='2.3', formatter_class=argparse.ArgumentDefaultsHelpFormatter) 
parser.add_argument('-w', '--workWith', 
        help = 'to specify a Gromacs exec suffix', 
        dest = 'wW', 
        action = 'store', 
        default = '-4.5.5-single', 
        ) 
parser.add_argument('-g', '--gro', 
        help = '.gro postfix: <nameOfTheDir><postfix>.gro', 
        dest = 'myGroPostfix', 
        action = 'store', 
        default = "_membrane", 
        ) 
parser.add_argument('-H', '--here', 
        help = 'toggles - single (current) dir behaviour (the output will be state.gro)', 
        dest = 'Here', 
        action = 'store_true', 
        ) 
parser.add_argument('-D', '--dirs', 
        help = 'include these dirs (python\'s rgxp in SINGLE quotes), defaults to \'\'', 
        dest = 'inclDirs', 
        action = 'store', 
        default = '', 
        ) 

args = parser.parse_args() 


print args.wW 

編集:さらに

gmx_bk-simulate-mems.py -j bk-runs-mpi.bash -p 1 -w="-4.5.5-double_non-parallel_gcc" 2&> ../`date +%Y-%b-%d-%H%M%S`.log & 

います:

gmx_bk-simulate-mems.py: error: unrecognized arguments: 2 

をそれはオプション(または2&>とオプションとして../date +%Y-%b-%d-%H%M%S.log)として​​扱い2&>のように見えます!

編集2

だから、要約する:​​については

  • から"-4.5.5-double_non-parallel_gcc"を不正なオプション名である - そして書くために必要とする理由ですが-w="-4.5.5-double_non-parallel_gcc"ようです。 optparsebash(!)の場合はこれで問題ありません。 bashでも-w="-4.5.5-double_non-parallel_gcc"にエラーが出ます - それはargが="-4.5.5-double_non-parallel_gcc"(!)だと思います。

  • 2&>のようなものはありません。 2>を使用する必要がありますが、エラーは発生しません。

  • ではなく、shellで、行をargsに分割します。

  • ​​は、optparseよりはるかに優れています。

+0

コードを 'tmp.py'に置くと、' python tmp.py -w3'と 'python tmp.py -w 3'の両方が私のために '3'を出力します。 – chepner

+0

@chepner:はいそれは...実際問題は、[gmx_bk-get-results.bash]の75行目になります(https://github.com/bk322/bk-bio/blob/master/gmx_bk-get-results)。 .bash):その行から '='を取り除くと、スクリプトはエラーを返します。私は '' $ wW ''を与えないかのようにします。再現するには[bk-copies-from-dirs.py](https://github.com/bk322/bk-goodies/blob/master/bk-copies-from-dirs.py)と[gmx_bk-cpt2gmx.py](https://github.com/bk322/bk-bio/blob/master/gmx_bk-cpt2gmx.py)...すべてが 'optparse'でうまくいきました。誰かがこの問題を「理論的に」見ることを願っています。 – Adobe

+1

脚本コメント:バージョンチェッカーは必要ありません。 Python 3を使用している場合、一番下のprintステートメントは構文エラーを引き起こし、スクリプトはロードされません。 Python 2.6以降を使用している場合、バージョンチェックに入る前に、スクリプトは 'argparse'をインポートすると失敗します。 – HardlyKnowEm

答えて

12

まず、小さな区別をする必要があります。​​モジュールは、コマンドライン引数を解析しません。シェルはコマンドライン引数を解析しません。シェルは、シェルで入力した行をトークンに変換します。、pythonの配列/コマンドライン引数のシーケンスに渡されます。​​モジュールは、sys.argvに表示される内容を単純に意味します。

この区別は、あなたが気づいた「エラー」の両方を明確にします。まず、-w "-4.5.5-double_non-parallel_gcc"(等号がないことに注意してください)を考えてみましょう。シェルはこれらの2つのトークンを-w-4.5.5-double_non-parallel_gccとして解析し、これらの文字列は両方ともsys.argvに渡されます。等号がなければ、これは2つのオプション(-w(引数なし))と-4.5.5-double_non-parallel_gccを引数として)のように見えます。すべてが単一のトークンとして解析されるように等号が必要です。 argparseが所与のトークンが引数として扱われているか否かを制御するため

EDITED SECTION 2&>として

、それは不可能です。 sys.argvに何かが現れると、シェルがそれを引数として扱っていることを意味します。

ここでの兆候はエラーメッセージです。メッセージはunrecognized arguments: 2&>ではなく、unrecognized arguments: 2であることに注意してください。シェルは "&>"を出力リダイレクションとして認識し、それに応じて残りの行(ログファイルを含む)を解析します。渡される唯一の引数は、2&>が実際のリダイレクトタイプではないため、 "2"です。 (&>はまだ2はそれに何を追加し、標準エラー出力と標準出力の両方をカバー?)

をコメントでは、あなたはoptparseは「2 &>」を「扱う」ことができると主張しました。実際にはそうではありません。 optparseモジュールは、正確に​​の機能を果たしましたが、optparseは、​​のような定位置引数を検証しません。実際には、optparseは実際のプログラミングエラー(この場合、2&>をシェルリダイレクトのタイプとして使用しています)を検出せずにスリップさせています!あなたは、元のoptparseのコードを投稿する必要がありますが、私は次のように、あなたの引数を解析された疑いがある:

opt, args = parser.parse_args() 

あなたのスクリプトには、位置引数を取りませんので、私はあなたが、その後argsで他に何もしなかった想像してみてください。しかし、argsを調べると、2が位置的な引数と見なされます。スクリプトは何も位置引数を取らず、あなたがoptparseを使用する場合、一般的に

は、あなたがそうのように、何の位置引数を受け取らないことを確認することをお勧めし:​​モジュールはあなたのためにその仕事をして

opt, args = parser.parse_args() 
if args: 
    parser.error("script takes no positional arguments") 

これは、他の理由の中でoptparseよりも先にマイルを置くものです。

+0

すべては 'optparse'でうまくいっていました。しかし、 '' -4.5.5-double_non-parallel_gcc ''は"悪いオプション名 "であり、' optparse'は引用符を残しているようですが、 '' argparse''はそうではありません。しかし、 '2&'部分はどうでしょうか? 'optparse'でうまくいきました。それは2: '&>'ではうまく動作しません。私はこのように生きることができます - しかしそれは奇妙ではありませんか?それは解決すべきです。それは '2&>'でも使えるはずです。 – Adobe

+0

私はあなたの懸念に対処するために上記の私の答えを編集しました。ここでも、 '2&'は実際のリダイレクションフラグではありません。 '2>'、 '&>'、 '2>&1'でもあり、' 2& 'ではありません。あなたが私を信じていないなら、 'ls 2&> tmp.txt'というシェルを組み込んで試してみてください。 '&>'はstderrをキャプチャします。すぐには表示されませんが、tmp.txtを見るとエラーメッセージが表示されます。 – HardlyKnowEm

+0

私は本当に 'args'を使ったことがありません。あなたはそれをすべて解決しました! – Adobe

関連する問題