2012-04-09 10 views
6

Nach dem Wechsel von optparse zu argparse - ich habe seltsame Fehler. Argparse args analysieren nur, wenn kein Platz verlassen:Python: Wechsel von optparse zu argparse

myScript.py -oOpt 

oder ein Gleichheitszeichen setzen:

myScript.py -o=Opt 

und es nicht die normale Art und Weise arbeiten:

myScript.py -o Opt 

Hier meine argparse Initialisierung ist :

#!/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 

bearbeiten:

Mehr noch:

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 & 

gibt:

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

es sieht aus wie argparse behandelt 2&> als Option (oder 2&> und ../date +%Y-%b-%d-%H%M%S.log als Optionen)!

Edit 2:

Um es zusammenzufassen:

  • Für argparse-"-4.5.5-double_non-parallel_gcc" ist eine schlechte Option Name - und deshalb ist es erforderlich, ist als -w="-4.5.5-double_non-parallel_gcc" zu schreiben. Für optparse und bash (!) Ist das in Ordnung. bash gibt sogar einen Fehler bei -w="-4.5.5-double_non-parallel_gcc" - es denkt, dass der arg ist ="-4.5.5-double_non-parallel_gcc" (!);

  • Es gibt keine 2&>. 2> sollte verwendet werden und es gibt keine Fehler;

  • Dies ist shell wer teilt die Zeile in Args, nicht python;

  • argparse ist viel besser als optparse.

+0

Setzen Sie Ihren Code in 'tmp.py', beide' python tmp.py -w3' und 'python tmp.py -w 3' drucken '3' für mich. – chepner

+0

@chepner: ja tut es ... Tatsächlich gibt das Problem Zeile 75 in [gmx_bk-get-results.bash] (https://github.com/bk322/bk-bio/blob/master/gmx_bk-get-results .bash): Wenn man '=' aus dieser Zeile entfernt, gibt das Skript einen Fehler aus - als ob ich es nicht "$ wW" 'geben würde. Um sich zu reproduzieren, braucht man auch [bk-copies-from-dirs.py] (https://github.com/bk322/bk-goodies/blob/master/bk-copies-from-dirs.py) und [gmx_bk-cpt2gmx.py] (https://github.com/bk322/bk-bio/blob/master/gmx_bk-cpt2gmx.py) ... Bei optparse lief alles gut. Ich hoffe, dass jemand das Problem "theoretisch" sehen wird. – Adobe

+1

Pedantischer Kommentar: Sie benötigen den Versionsüberprüfer nicht. Wenn Sie Python 3 verwenden, führt die Druckanweisung am Ende zu einem Syntaxfehler und das Skript wird nicht einmal geladen. Wenn Sie Python 2.6 oder niedriger verwenden, schlägt das Skript beim Importieren von 'argparse' fehl, bevor Sie sogar zur Versionsüberprüfung gelangen. – HardlyKnowEm

Antwort

12

Zunächst ist es notwendig, einen kleinen Unterschied zu machen. Das Modul argparse analysiert Ihre Befehlszeilenargumente nicht, die Shell tut dies. Die Shell ist verantwortlich für die Umwandlung der Zeile, die Sie in der Shell eingeben, in Token, die dann an sys.argv, ein Python-Array/eine Folge von Befehlszeilenargumenten übergeben werden. Das argparse Modul macht einfach Sinn was in sys.argv erscheint.

Diese Unterscheidung wird beide "Fehler" verdeutlichen, die Sie bemerkt haben. Betrachten Sie zuerst -w "-4.5.5-double_non-parallel_gcc" (beachten Sie das Fehlen des Gleichheitszeichens). Die Shell analysiert diese beiden Tokens als -w und -4.5.5-double_non-parallel_gcc, und beide Zeichenfolgen werden an sys.argv übergeben. Ohne das Gleichheitszeichen scheinen dies zwei Optionen zu sein: -w (ohne Argument) und -4 mit .5.5-double_non-parallel_gcc als Argument.Sie benötigen das Gleichheitszeichen, damit alles als einzelnes Token analysiert wird.

EDITED SECTION

Wie für 2&>, ist es unmöglich für argparse zu steuern, ob ein gegebenes Token als Argument behandelt wird oder nicht. Wenn etwas in sys.argv angezeigt wird, bedeutet das, dass Ihre Shell es als ein Argument behandelt.

Das verräterische Zeichen hier ist die Fehlermeldung. Beachten Sie, dass die Nachricht nicht unrecognized arguments: 2&> ist, sondern unrecognized arguments: 2. Ihre Shell erkennt "&>" als Ausgabeumleitung und analysiert den Rest der Zeile (einschließlich der Protokolldatei) entsprechend. Das einzige Argument, das übergeben wird, ist die "2", da 2&> keine echte Art der Umleitung ist. (&> deckt bereits sowohl stderr und stdout, so würde, was die 2 ihm hinzufügen?)

In einem Kommentar, behauptete man, dass optparse könnte "Griff" die "2 &>". Das ist nicht wirklich der Fall. Das Modul optparse hat genau das gemacht, was argparse tut, aber optparse validiert Positionsargumente wie argparse nicht. In der Tat, optparse lässt einen echten Programmierfehler (in diesem Fall mit 2&> als eine Art Shell-Umleitung) durch unbemerkt Schlüpfen! Sie sollten Ihren ursprünglichen optparse Code schreiben, aber ich vermute, dass Sie Ihre Argumente analysiert, wie folgt:

opt, args = parser.parse_args() 

Ihr Skript nimmt keine Positionsargumente, so dass ich denke, Sie tat nichts anderes mit args danach. Aber wenn Sie args inspizieren würden, würden Sie finden, dass 2 als Positionsargument betrachtet wurde!

Im Allgemeinen, wenn ein Skript keine Positions Argumente übernimmt und Sie optparse, ist es gute Praxis, um sicherzustellen, dass Sie keine Positionsargumente erhalten, etwa so:

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

Das argparse Modul funktioniert das für Sie Das ist es, was es aus anderen Gründen Meilen voraus optparse setzt.

+0

Alles funktionierte gut mit 'optparse'. Aber es sieht so aus als ob "-4.5.5-double_non-parallel_gcc" 'ein" falscher Optionsname "ist, und während" optparse "die Anführungszeichen verlässt," argparse "nicht - daher der Fehler. Aber was ist mit dem '2 &>' Teil? Es funktionierte gut mit 'optparse'. Es funktioniert gut mit 2: '&>'. Ich kann so leben - aber ist es nicht seltsam? Es sollte gelöst werden. Es sollte auch mit '2 &>' funktionieren. – Adobe

+0

Ich habe meine Antwort oben bearbeitet, um auf Ihre Bedenken einzugehen. Auch hier ist '2 &>' kein echtes Umleitungsflag; '2>' ist, und '&>' ist und sogar '2> & 1', aber nicht' 2 &> '. Wenn Sie mir nicht glauben, versuchen Sie es mit einer eingebauten Shell: 'ls 2 &> tmp.txt'. Das '&>' fängt stderr auf, so dass Sie es nicht sofort sehen werden, aber wenn Sie tmp.txt betrachten, sehen Sie die Fehlermeldung. – HardlyKnowEm

+0

Ich habe '' Args 'tatsächlich nie benutzt. Also hast du alles gelöst! – Adobe