Tentukan format untuk argumen masukan argparse python

111

Saya memiliki skrip python yang memerlukan beberapa input baris perintah dan saya menggunakan argparse untuk menguraikannya. Saya menemukan dokumentasinya agak membingungkan dan tidak dapat menemukan cara untuk memeriksa format dalam parameter input. Yang saya maksud dengan memeriksa format dijelaskan dengan skrip contoh ini:

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__)))

Saya perlu memeriksa opsi -sdan -ebahwa input oleh pengguna ada dalam format YYYY-MM-DD. Apakah ada opsi di argparse yang saya tidak tahu yang menyelesaikan ini.

Sohaib
sumber

Jawaban:

235

Sesuai dokumentasi :

The typeargumen kata kunci add_argument()memungkinkan setiap jenis-memeriksa dan jenis yang diperlukan konversi yang akan dilakukan ... type=dapat mengambil callable yang mengambil string argumen tunggal dan kembali dikonversi nilai

Anda bisa melakukan sesuatu seperti:

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)

Kemudian gunakan itu sebagai type:

parser.add_argument("-s", 
                    "--startdate", 
                    help="The Start Date - format YYYY-MM-DD", 
                    required=True, 
                    type=valid_date)
jonrsharpe
sumber
Tentang pertanyaan lain yang Anda edit, bisakah Anda mengarahkan saya ke dokumentasi (jika ada) untuk itu?
Sohaib
Apakah valid_date()menganggap argumen yang diberikan adalah string?
Stevoisiak
1
@StevenVascellaro ya, tapi itulah yang didefinisikan oleh API; "mengambil argumen string tunggal" per kutipan dari dokumen.
jonrsharpe
71

Hanya untuk menambahkan jawaban di atas, Anda dapat menggunakan fungsi lambda jika Anda ingin menyimpannya dalam satu baris. Sebagai contoh:

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

Utas lama tetapi pertanyaan itu masih relevan bagi saya setidaknya!

Evan V
sumber
6
Ini adalah trik yang bagus, meskipun jika Anda memberikan sesuatu yang tidak valid, pesan kesalahannya hanya akaninvalid <lambda> value
Brad Solomon
38

Untuk orang lain yang menggunakan ini melalui mesin pencari: dengan Python 3.7, Anda dapat menggunakan .fromisoformatmetode kelas standar daripada menciptakan kembali roda untuk tanggal yang sesuai dengan ISO-8601, misalnya:

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)
Michał Górny
sumber
5
Selain itu, dateutil's ISO parser mengambil sejumlah fmts tambahan yang masih ISO 8601-2004 compliant. Anda dapat menggunakan import dateutil.parser-> type=dateutil.parser.isoparseatautype=dateutil.parser.parse
Brad Solomon
@BradSolomon Memang saran yang bagus (karena itu +1 saya), tetapi dateutilmerupakan paket pihak ketiga. Seseorang harus menilai manfaatnya terhadap kerumitan (kecil) untuk menginstalnya secara ekstra. YMMV.
Laryx Decidua