Especifique o formato dos argumentos de entrada argparse python


111

Eu tenho um script python que requer algumas entradas de linha de comando e estou usando argparse para analisá-los. Achei a documentação um pouco confusa e não consegui encontrar uma maneira de verificar se há um formato nos parâmetros de entrada. O que quero dizer com verificação de formato é explicado com este script de exemplo:

parser.add_argument('-s', "--startdate", help="The Start Date - format YYYY-MM-DD ", required=True)
parser.add_argument('-e', "--enddate", help="The End Date format YYYY-MM-DD (Inclusive)", required=True)
parser.add_argument('-a', "--accountid", type=int, help='Account ID for the account for which data is required (Default: 570)')
parser.add_argument('-o', "--outputpath", help='Directory where output needs to be stored (Default: ' + os.path.dirname(os.path.abspath(__file__)))

Preciso verificar se há opção -se se -ea entrada do usuário está no formato YYYY-MM-DD. Existe uma opção em argparse que eu não sei que realiza isso.

Respostas:


235

Pela documentação :

O typeargumento de palavra-chave de add_argument()permite que qualquer verificação de tipo e conversões de tipo sejam realizadas ... type=pode receber qualquer chamável que receba um único argumento de string e retorne o valor convertido

Você poderia fazer algo como:

def valid_date(s):
    try:
        return datetime.strptime(s, "%Y-%m-%d")
    except ValueError:
        msg = "Not a valid date: '{0}'.".format(s)
        raise argparse.ArgumentTypeError(msg)

Então use isso como type:

parser.add_argument("-s", 
                    "--startdate", 
                    help="The Start Date - format YYYY-MM-DD", 
                    required=True, 
                    type=valid_date)

Sobre a outra questão que você editou, você pode me apontar a documentação (se houver) para isso?
Sohaib de

Presume valid_date()que o argumento fornecido é uma string?
Stevoisiak

1
@StevenVascellaro sim, mas é o que a API define; "leva um único argumento de string" de acordo com a citação dos documentos.
jonrsharpe

71

Apenas para complementar a resposta acima, você pode usar uma função lambda se quiser mantê-la em uma linha. Por exemplo:

parser.add_argument('--date', type=lambda d: datetime.strptime(d, '%Y%m%d'))

Tópico antigo, mas a questão ainda era relevante para mim, pelo menos!


6
Este é um bom truque, embora se você passar algo inválido, a mensagem de erro será apenasinvalid <lambda> value
Brad Solomon

38

Para outras pessoas que conseguiram isso por meio de mecanismos de pesquisa: no Python 3.7, você pode usar o .fromisoformatmétodo de classe padrão em vez de reinventar a roda para datas compatíveis com ISO-8601, por exemplo:

parser.add_argument('-s', "--startdate",
    help="The Start Date - format YYYY-MM-DD",
    required=True,
    type=datetime.date.fromisoformat)
parser.add_argument('-e', "--enddate",
    help="The End Date format YYYY-MM-DD (Inclusive)",
    required=True,
    type=datetime.date.fromisoformat)

5
Além disso, dateutilo analisador ISO de usa vários fmts adicionais que ainda são compatíveis com ISO 8601-2004. Você pode usar import dateutil.parser-> type=dateutil.parser.isoparseoutype=dateutil.parser.parse
Brad Solomon

@BradSolomon De fato uma boa sugestão (daí meu +1), mas dateutilé um pacote de terceiros. Seria preciso avaliar seus benefícios em relação ao (pequeno) incômodo de instalá-lo extra. YMMV.
Laryx Decidua
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.