2012-04-09 17 views
6

Después de cambiar de optparse a argparse - Estoy experimentando errores extraños. Argparse analizar args sólo si no dejar ningún espacio:Python: cambio de optparse a argparse

myScript.py -oOpt 

o poner un signo igual:

myScript.py -o=Opt 

y no funciona de la forma habitual:

myScript.py -o Opt 

Aquí es mi argparse inicialización :

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

Editar:

Aún más:

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 & 

da:

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

parece que argparse trata 2&> como opción (o 2&> y ../date +%Y-%b-%d-%H%M%S.log como opciones)!

Editar 2:

Entonces, para resumir:

  • Para argparse - "-4.5.5-double_non-parallel_gcc" es un nombre de opción malo - y es por eso que se requiere para escribir es como -w="-4.5.5-double_non-parallel_gcc". Para optparse y bash (!) Esto está bien. bash incluso da un error al -w="-4.5.5-double_non-parallel_gcc" - cree que el argumento es ="-4.5.5-double_non-parallel_gcc" (!);

  • No existe tal cosa como 2&>. 2> debería ser usado y no da errores;

  • Esto es shell que divide la línea en args, no python;

  • argparse es mucho mejor que optparse.

+0

Poniendo tu código en 'tmp.py', tanto' python tmp.py -w3' como 'python tmp.py -w 3' imprime '3' para mí. – chepner

+0

@chepner: sí lo hace ... En realidad, el problema da la línea 75 en [gmx_bk-get-results.bash] (https://github.com/bk322/bk-bio/blob/master/gmx_bk-get-results .bash): si uno elimina '=' de esa línea - el script da error - como si no le diera '" $ wW "'. Para poder reproducir uno también se necesita obtener [bk-copies-from-dirs.py] (https://github.com/bk322/bk-goodies/blob/master/bk-copies-from-dirs.py) y [gmx_bk-cpt2gmx.py] (https://github.com/bk322/bk-bio/blob/master/gmx_bk-cpt2gmx.py) ... Todo funcionaba bien en 'optparse'. Espero que alguien vea el problema "teóricamente". – Adobe

+1

comentario pedante: no necesita el verificador de versión. Si usa Python 3, la instrucción de impresión en la parte inferior causará un error de sintaxis y el script ni siquiera se cargará. Si usa Python 2.6 o posterior, la secuencia de comandos fallará al importar 'argparse', incluso antes de llegar a la verificación de versión. – HardlyKnowEm

Respuesta

12

En primer lugar, es necesario hacer una pequeña distinción. El módulo argparse no analiza los argumentos de la línea de comandos, el shell sí lo hace. El intérprete de comandos es responsable de transformar la línea que escribes en el intérprete de comandos en tokens, que luego pasan a sys.argv, una matriz de Python/secuencia de argumentos de línea de comandos. El módulo argparse simplemente tiene sentido de lo que aparece en sys.argv.

Esta distinción aclarará los "errores" que ha notado. En primer lugar, considere -w "-4.5.5-double_non-parallel_gcc" (tenga en cuenta la falta de igual signo). El shell analiza estos dos tokens como -w y -4.5.5-double_non-parallel_gcc, y ambas cadenas se pasan a sys.argv. Sin el signo igual, esto parece ser dos opciones: -w (sin argumento) y -4 con .5.5-double_non-parallel_gcc como argumento.Necesita el signo igual para que todo se analice como un token único.

sección editada

cuanto a 2&>, es imposible para argparse para controlar si un contador dado es tratado como un argumento o no. Si algo aparece en sys.argv, significa que su shell lo está tratando como un argumento.

El signo revelador aquí es el mensaje de error. Tenga en cuenta que el mensaje no es unrecognized arguments: 2&>, sino más bien, unrecognized arguments: 2. Su shell reconoce "&>" como redirección de salida y analiza el resto de la línea (incluido el archivo de registro) en consecuencia. El único argumento que se pasa es el "2", porque 2&> no es un tipo real de redirección. (&> ya cubre tanto stderr y stdout, así que lo que sería el 2 agregar a ella?)

En un comentario, que declaró que optparse podría "manejar" el "2 &>". Ese no es realmente el caso. El módulo optparse hizo exactamente lo que argparse hace, pero optparse no valida argumentos posicionales como argparse. De hecho, optparse está dejando pasar un error de programación real (en este caso, usando 2&> como un tipo de redirección de shell) deslizándose por no detectado. Usted debe publicar su código optparse original, pero sospecho que Analizada sus argumentos de la siguiente manera:

opt, args = parser.parse_args() 

Su guión no tiene argumentos posicionales, así que me imagino que hizo nada más con args después. Pero si tuviera que inspeccionar args, ¡encontraría que 2 se consideró un argumento posicional!

En general, si un guión no tiene argumentos posicionales y se utiliza optparse, es una buena práctica para verificar que recibes no hay argumentos posicionales, así:

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

El módulo argparse hace que el trabajo para usted , que es lo que lo pone millas por delante de optparse (entre otras razones).

+0

Todo funcionaba bien con 'optparse'. Pero parece que '" -4.5.5-double_non-parallel_gcc "' es un "mal nombre de opción", y mientras 'optparse' deja las comillas,' argparse' no lo hace - de ahí el error. Pero, ¿qué pasa con la parte '2 &>'? Funcionó bien con 'optparse'. Funciona bien con no 2: '&>'. Puedo vivir de esta manera, pero ¿no es extraño? Debería ser resuelto. Debería funcionar con '2 &>' también. – Adobe

+0

He editado mi respuesta anterior para abordar su inquietud. De nuevo, '2 &>' no es una bandera de redirección real; '2>' es, y '&>' es, e incluso '2> & 1', pero no' 2 &> '. Si no me crees, pruébalo con un shell incorporado: 'ls 2 &> tmp.txt'. El '&>' captura stderr, por lo que no lo verá de inmediato, pero si mira tmp.txt verá el mensaje de error. – HardlyKnowEm

+0

Nunca he usado 'args' de hecho. ¡Así que lo resolvió todo! – Adobe

Cuestiones relacionadas