2012-04-09 20 views
6

Dopo il passaggio da optparse a argparse, si verificano strani errori. Argparse analizzare args solo se non lasciano spazio:Python: passaggio da optparse a argparse

myScript.py -oOpt 

o mettere un segno di uguale:

myScript.py -o=Opt 

e non funziona il modo normale:

myScript.py -o Opt 

Ecco la mia inizializzazione 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 

Edit:

Ancor più:

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 & 

dà:

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

sembra argparse tratta 2&> in opzione (o 2&> e ../date +%Y-%b-%d-%H%M%S.log come opzioni)!

Edit 2:

Quindi, per riassumere:

  • Per argparse-"-4.5.5-double_non-parallel_gcc" è un nome di opzione male - ed è per questo che è necessario per scrivere è come -w="-4.5.5-double_non-parallel_gcc". Per optparse e bash (!) Questo va bene. bash restituisce anche un errore a -w="-4.5.5-double_non-parallel_gcc" - si pensa che l'argomento sia ="-4.5.5-double_non-parallel_gcc" (!);

  • Non esiste una cosa come 2&>. 2> dovrebbe essere usato e non dà errori;

  • Questo è shell chi divide la linea in args, non python;

  • argparse è molto meglio di optparse.

+0

Inserire il codice in 'tmp.py', sia' python tmp.py -w3' che 'python tmp.py -w 3' stampa '3' per me. – chepner

+0

@chepner: sì sì ... In realtà il problema dà la riga 75 in [gmx_bk-get-results.bash] (https://github.com/bk322/bk-bio/blob/master/gmx_bk-get-results .bash): se si rimuove '=' da quella linea - lo script dà errore - come se non gli dessi '" $ wW "'. Per riprodurlo bisogna anche ottenere [bk-copies-from-dirs.py] (https://github.com/bk322/bk-goodies/blob/master/bk-copies-from-dirs.py) e [gmx_bk-cpt2gmx.py] (https://github.com/bk322/bk-bio/blob/master/gmx_bk-cpt2gmx.py) ... Tutto funzionava bene su 'optparse'. Spero che qualcuno vedrà il problema "teoricamente". – Adobe

+1

Commento pedante: non è necessario il correttore di versione. Se si utilizza Python 3, l'istruzione print in basso causerà un errore di sintassi e lo script non verrà nemmeno caricato. Se usi Python 2.6 o versioni precedenti, lo script fallirà con l'importazione di 'argparse', prima ancora di arrivare al controllo della versione. – HardlyKnowEm

risposta

12

In primo luogo, è necessario fare una piccola distinzione. Il modulo argparse non analizza gli argomenti della riga di comando, come fa la shell. La shell è responsabile della trasformazione della riga che si digita nella shell in token, che vengono quindi passati a sys.argv, una matrice python/sequenza di argomenti della riga di comando. Il modulo argparse ha semplicemente un senso di ciò che appare in sys.argv.

Questa distinzione servirà a chiarire entrambi gli "errori" che hai notato. Innanzitutto, considera -w "-4.5.5-double_non-parallel_gcc" (nota la mancanza del segno di uguale). La shell analizza questi due token come -w e -4.5.5-double_non-parallel_gcc e entrambe le stringhe vengono passate a sys.argv. Senza il segno di uguale, questa sembra essere due opzioni: -w (senza argomenti) e -4 con .5.5-double_non-parallel_gcc come argomento.È necessario il segno di uguale in modo che tutto sia analizzato come un singolo token.

SEZIONE MODIFICATI

Quanto 2&>, è impossibile per argparse per controllare se un dato token è trattato come un argomento o meno. Se qualcosa appare in sys.argv, significa che la tua shell lo considera come argomento.

Il segnale di conferma qui è il messaggio di errore. Si noti che il messaggio non è unrecognized arguments: 2&>, ma piuttosto, unrecognized arguments: 2. La shell riconosce "&>" come reindirizzamento dell'output e analizza di conseguenza il resto della riga (incluso il file di registro). L'unico argomento passato è il "2", perché 2&> non è un vero tipo di reindirizzamento. (&> comprende già sia stderr e stdout, così che cosa sarebbe la 2 aggiungere ad essa?)

In un commento, si sosteneva che optparse potrebbe "gestire" il "2 &>". Questo non è in realtà il caso. Il modulo optparse ha fatto esattamente ciò che fa argparse, ma optparse non convalida argomenti posizionali come argparse. Infatti, optparse sta dando un vero errore di programmazione (in questo caso, usando 2&> come un tipo di reindirizzamento della shell) slip inosservato! Si dovrebbe pubblicare il tuo codice di optparse originale, ma ho il sospetto che i vostri argomenti analizzati come segue:

opt, args = parser.parse_args() 

Lo script non ha argomenti posizionali, quindi immagino che hai fatto niente altro con args dopo. Ma se dovessi ispezionare args, vedresti che 2 è stato considerato un argomento posizionale!

In generale, se uno script non accetta argomenti posizionali e si utilizza optparse, è buona norma verificare che non si ricevono argomenti posizionali, in questo modo:

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

Il modulo argparse fa il lavoro per voi , che è ciò che lo mette miglia avanti a optparse (tra gli altri motivi).

+0

Tutto funzionava bene con 'optparse'. Ma sembra che "" -4.5.5-double_non-parallel_gcc "' sia un "nome opzione errato", e mentre 'optparse' lascia le virgolette,' argparse' no - da qui l'errore. Ma per quanto riguarda la parte '2 &>'? Funzionava bene con 'optparse'. Funziona bene con no 2: '&>'. Posso vivere in questo modo - ma non è strano? Dovrebbe essere risolto. Dovrebbe funzionare anche con '2 &>' – Adobe

+0

Ho modificato la mia risposta sopra per rispondere alla tua preoccupazione. Ancora, '2 &>' non è una vera bandiera di reindirizzamento; '2>' è, e '&>' è, e anche '2> & 1', ma non' 2 &> '. Se non mi credi, prova con una shell integrata: "ls 2 &> tmp.txt". '&>' Cattura stderr, quindi non lo vedrai immediatamente, ma se guardi tmp.txt vedrai il messaggio di errore. – HardlyKnowEm

+0

Non ho mai usato 'args' in effetti. Quindi hai risolto tutto! – Adobe