web-dev-qa-db-fra.com

Pourquoi en argparse, un «vrai» est toujours «vrai»?

Voici le script Python le plus simple, nommé test.py:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--bool', default=True, type=bool, help='Bool type')
args = parser.parse_args()
print(args.bool)

Mais quand j'exécute ce code sur la ligne de commande:

python test.py --bool False
True

Alors que quand mon code lit '--bool', default=False, l'argparse fonctionne correctement.

Pourquoi?

22
Lu Zhang

Vous ne passez pas l'objet False. Vous passez dans le 'False' chaîne, et c'est une chaîne de longueur non nulle.

Seule une chaîne de longueur 0 est testée comme fausse:

>>> bool('')
False
>>> bool('Any other string is True')
True
>>> bool('False')  # this includes the string 'False'
True

Utiliser un store_true ou store_false action à la place. Pour default=True, utilisation store_false:

parser.add_argument('--bool', default=True, action='store_false', help='Bool type')

Omettant maintenant les jeux de commutateurs args.bool à True, en utilisant --bool (sans autre argument) définit args.bool à False:

python test.py
True

python test.py --bool
False

Si vous devez analyser une chaîne contenant True ou False, vous devrez le faire explicitement:

def boolean_string(s):
    if s not in {'False', 'True'}:
        raise ValueError('Not a valid boolean string')
    return s == 'True'

et utilisez-le comme argument de conversion:

parser.add_argument('--bool', default=True, type=boolean_string, help='Bool type')

à quel point --bool False fonctionnera comme prévu.

30
Martijn Pieters