Chỉ định định dạng cho các đối số đầu vào argparse python


111

Tôi có một tập lệnh python yêu cầu một số đầu vào dòng lệnh và tôi đang sử dụng argparse để phân tích cú pháp chúng. Tôi thấy tài liệu hơi khó hiểu và không thể tìm cách kiểm tra định dạng trong các tham số đầu vào. Ý tôi là gì khi kiểm tra định dạng được giải thích với tập lệnh mẫu này:

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

Tôi cần kiểm tra tùy chọn -s-eđầu vào của người dùng có ở định dạng không YYYY-MM-DD. Có một tùy chọn nào trong argparse mà tôi không biết trong số đó hoàn thành việc này.

Câu trả lời:


235

Theo tài liệu :

Đối typesố từ khóa của add_argument()cho phép thực hiện bất kỳ chuyển đổi loại và kiểm tra kiểu cần thiết nào ... type=có thể nhận bất kỳ lệnh có thể gọi nào nhận đối số chuỗi đơn và trả về giá trị đã chuyển đổi

Bạn có thể làm điều gì đó như:

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)

Sau đó, sử dụng nó như type:

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

Về câu hỏi khác mà bạn đã chỉnh sửa, bạn có thể chỉ cho tôi tài liệu (nếu có) cho điều đó không?
Sohaib

valid_date()giả lập luận đưa ra là một chuỗi?
Stevoisiak

1
@StevenVascellaro vâng, nhưng đó là những gì API định nghĩa; "lấy một đối số chuỗi đơn" cho mỗi trích dẫn từ tài liệu.
jonrsharpe

71

Chỉ cần thêm vào câu trả lời ở trên, bạn có thể sử dụng một hàm lambda nếu bạn muốn giữ nó trong một lớp lót. Ví dụ:

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

Chủ đề cũ nhưng câu hỏi vẫn còn phù hợp với tôi ít nhất!


6
Đây là một thủ thuật rất hay, mặc dù nếu bạn vượt qua một cái gì đó không hợp lệ, thông báo lỗi sẽ chỉ đượcinvalid <lambda> value
Brad Solomon

38

Đối với những người khác gặp phải vấn đề này thông qua công cụ tìm kiếm: trong Python 3.7, bạn có thể sử dụng .fromisoformatphương pháp lớp tiêu chuẩn thay vì phát minh lại bánh xe cho các ngày tuân thủ ISO-8601, ví dụ:

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
Bên cạnh đó, dateutil's phân tích cú pháp ISO mất một số các FMT bổ sung mà vẫn được chứng nhận ISO 8601-2004 tuân thủ. Bạn có thể sử dụng import dateutil.parser-> type=dateutil.parser.isoparsehaytype=dateutil.parser.parse
Brad Solomon

@BradSolomon Quả thực là một gợi ý hay (do đó là +1 của tôi), nhưng dateutillà một gói của bên thứ ba. Người ta sẽ phải đánh giá lợi ích của nó so với rắc rối (nhỏ) của việc cài đặt thêm nó. YMMV.
Laryx Decidua
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.