Al principio pensé lo mismo que jcollado, pero luego está el hecho de que, si el (primer nivel) argumentos posicionales subsiguientes tienen una específica nargs
(nargs
= None
, nargs
= entero), entonces funciona como se espera. Falla cuando nargs
es '?'
o '*'
, y algunas veces cuando es '+'
. Entonces, fui al código, para descubrir qué está pasando.
Todo se reduce a la forma en que los argumentos se dividen para ser consumidos. Para averiguar quién recibe qué, la llamada al parse_args
resume los argumentos en una cadena como 'AA'
, en su caso ('A'
para argumentos posicionales, 'O'
para opcional), y termina produciendo un patrón de expresiones regulares para coincidir con esa cadena de resumen, dependiendo sobre las acciones que ha agregado al analizador a través de los métodos .add_argument
y .add_subparsers
.
En todos los casos, para su ejemplo, la cadena de argumento termina siendo 'AA'
. Lo que cambia es el patrón que se emparejará (puede ver los patrones posibles en _get_nargs_pattern
en argparse.py
. Para subpositional
termina siendo '(-*A[-AO]*)'
, lo que significa permite un argumento seguido de cualquier número de opciones o argumentos.Para positional
, que depende del valor pasado a nargs
:
None
=>'(-*A-*)'
- 3 =>
'(-*A-*A-*A-*)'
(uno '-*A'
por argumento esperado)
'?'
=>'(-*A?-*)'
'*'
=>'(-*[A-]*)'
'+'
=>'(-*A[A-]*)'
Esos patrones se anexan y, por nargs=None
(el ejemplo de trabajo), que terminan con '(-*A[-AO]*)(-*A-*)'
, que coincide con dos grupos ['A', 'A']
. De esta forma, subpositional
analizará solo subpositional
(lo que deseaba), mientras que positional
coincidiría con su acción.
Para nargs='?'
, sin embargo, termina con '(-*A[-AO]*)(-*A?-*)'
. El segundo grupo está compuesto completamente por patrones opcionales, y *
codicioso, lo que significa que el primer grupo engloba todo en la cadena, terminando por reconocer los dos grupos ['AA', '']
. Esto significa subpositional
obtiene dos argumentos, y termina estrangulándose, por supuesto.
divertido lo suficiente, el patrón de nargs='+'
es '(-*A[-AO]*)(-*A[A-]*)'
, que trabaja , siempre y cuando sólo se pasa un argumento. Diga subpositional a
, ya que necesita al menos un argumento posicional en el segundo grupo. De nuevo, como el primer grupo es codicioso, al pasar subpositional a b c d
obtienes ['AAAA', 'A']
, que no es lo que querías.
En resumen: un desastre. Creo que esto debe ser considerado un error, pero no está seguro de cuál sería el impacto si los patrones se convierten en los no codiciosos ...
Por cierto, parece un [fallo conocido ] (http://bugs.python.org/issue9340), que se ha corregido para las versiones recientes de Python. –