optparse --- Trình phân tích cú pháp cho các tùy chọn dòng lệnh

Source code: Lib/optparse.py


Chọn thư viện phân tích đối số

Thư viện chuẩn bao gồm ba thư viện phân tích đối số:

  • getopt: một mô-đun phản ánh chặt chẽ thủ tục C getopt API. Được bao gồm trong thư viện chuẩn kể từ trước khi phát hành Python 1.0 ban đầu.

  • optparse: một sự thay thế khai báo cho getopt cung cấp chức năng tương đương mà không yêu cầu mỗi ứng dụng triển khai logic phân tích cú pháp tùy chọn thủ tục của riêng nó. Được bao gồm trong thư viện chuẩn kể từ khi phát hành Python 2.3.

  • argparse: một giải pháp thay thế đáng tin cậy hơn cho optparse, cung cấp nhiều chức năng hơn theo mặc định, nhưng lại làm giảm tính linh hoạt của ứng dụng trong việc kiểm soát chính xác cách xử lý đối số. Được bao gồm trong thư viện chuẩn kể từ bản phát hành Python 2.7 và Python 3.2.

Trong trường hợp không có các ràng buộc thiết kế phân tích cú pháp đối số cụ thể hơn, argparse là lựa chọn được đề xuất để triển khai các ứng dụng dòng lệnh vì nó cung cấp chức năng cơ bản ở mức cao nhất với ít mã cấp ứng dụng nhất.

getopt được giữ lại gần như hoàn toàn vì lý do tương thích ngược. Tuy nhiên, nó cũng phục vụ một trường hợp sử dụng thích hợp như một công cụ để tạo nguyên mẫu và kiểm tra việc xử lý đối số dòng lệnh trong các ứng dụng C dựa trên getopt.

optparse nên được coi là thay thế cho argparse trong các trường hợp sau:

  • một ứng dụng đã sử dụng optparse và không muốn mạo hiểm với những thay đổi hành vi tinh vi có thể phát sinh khi di chuyển sang argparse

  • ứng dụng yêu cầu quyền kiểm soát bổ sung đối với cách xen kẽ các tùy chọn và tham số vị trí trên dòng lệnh (bao gồm khả năng tắt hoàn toàn tính năng xen kẽ)

  • ứng dụng yêu cầu kiểm soát bổ sung đối với việc phân tích cú pháp gia tăng các thành phần dòng lệnh (mặc dù argparse có hỗ trợ điều này, nhưng cách hoạt động chính xác của nó trong thực tế là không mong muốn đối với một số trường hợp sử dụng)

  • ứng dụng yêu cầu quyền kiểm soát bổ sung đối với việc xử lý các tùy chọn chấp nhận các giá trị tham số có thể bắt đầu bằng - (chẳng hạn như các tùy chọn được ủy quyền sẽ được chuyển đến các quy trình con được gọi)

  • ứng dụng yêu cầu một số hành vi xử lý tham số dòng lệnh khác mà argparse không hỗ trợ, nhưng có thể được triển khai theo giao diện cấp thấp hơn do optparse cung cấp

Những cân nhắc này cũng có nghĩa là optparse có khả năng cung cấp nền tảng tốt hơn cho các tác giả thư viện viết thư viện xử lý đối số dòng lệnh của bên thứ ba.

Để làm ví dụ cụ thể, hãy xem xét hai cấu hình phân tích cú pháp đối số dòng lệnh sau, cấu hình đầu tiên sử dụng optparse và cấu hình thứ hai sử dụng argparse:

nhập khẩu optparse

nếu __name__ == '__main__':
    trình phân tích  pháp = optparse.OptionParser()
    parser.add_option('-o', '--output')
    parser.add_option('-v', dest='verbose', action='store_true')
    opts, args = parser.parse_args()
    quá trình (args, đầu ra=opts.output, chi tiết=opts.verbose)
nhập khẩu argparse

nếu __name__ == '__main__':
    trình phân tích  pháp = argparse.ArgumentParser()
    parser.add_argument('-o', '--output')
    parser.add_argument('-v', dest='verbose', action='store_true')
    parser.add_argument('rest', nargs='*')
    args = trình phân tích  pháp.parse_args()
    quá trình(args.rest, đầu ra=args.output, chi tiết=args.verbose)

Sự khác biệt rõ ràng nhất là ở phiên bản optparse, các đối số không phải tùy chọn được ứng dụng xử lý riêng sau khi quá trình xử lý tùy chọn hoàn tất. Trong phiên bản argparse, các đối số vị trí được khai báo và xử lý giống như các tùy chọn đã đặt tên.

Tuy nhiên, phiên bản argparse cũng sẽ xử lý một số tổ hợp tham số khác với cách phiên bản optparse xử lý chúng. Ví dụ (trong số những khác biệt khác):

  • việc cung cấp -o -v sẽ mang lại output="-v"verbose=False khi sử dụng optparse, nhưng có lỗi sử dụng với argparse (phàn nàn rằng không có giá trị nào được cung cấp cho -o/--output, vì -v được hiểu là cờ chi tiết)

  • tương tự, việc cung cấp -o -- sẽ mang lại output="--"args=() khi sử dụng optparse, nhưng có lỗi sử dụng với argparse (cũng phàn nàn rằng không có giá trị nào được cung cấp cho -o/--output, vì -- được hiểu là chấm dứt quá trình xử lý tùy chọn và coi tất cả các giá trị còn lại là đối số vị trí)

  • việc cung cấp -o=foo sẽ cung cấp output="=foo" khi sử dụng optparse, nhưng cung cấp output="foo" với argparse (vì = được đặt trong trường hợp đặc biệt như một dấu phân cách thay thế cho các giá trị tham số tùy chọn)

Việc những hành vi khác nhau này trong phiên bản argparse được coi là mong muốn hay có vấn đề sẽ tùy thuộc vào trường hợp sử dụng ứng dụng dòng lệnh cụ thể.

Xem thêm

click là thư viện xử lý đối số của bên thứ ba (ban đầu dựa trên optparse), cho phép phát triển các ứng dụng dòng lệnh dưới dạng một tập hợp các chức năng thực thi lệnh được trang trí.

Các thư viện bên thứ ba khác, chẳng hạn như typer hoặc msgspec-click, cho phép chỉ định giao diện dòng lệnh theo cách tích hợp hiệu quả hơn với việc kiểm tra tĩnh các chú thích loại Python.

Giới thiệu

optparse là một thư viện thuận tiện, linh hoạt và mạnh mẽ hơn để phân tích các tùy chọn dòng lệnh so với mô-đun getopt tối giản. optparse sử dụng kiểu phân tích cú pháp dòng lệnh mang tính khai báo hơn: bạn tạo một phiên bản của OptionParser, điền vào đó các tùy chọn và phân tích cú pháp dòng lệnh. optparse cho phép người dùng chỉ định các tùy chọn theo cú pháp GNU/POSIX thông thường, đồng thời tạo thêm thông báo sử dụng và trợ giúp cho bạn.

Đây là ví dụ về cách sử dụng optparse trong một tập lệnh đơn giản:

từ nhập optparse OptionParser
...
trình phân tích  pháp = OptionParser()
parser.add_option("-f", "--file", dest="filename",
                  help="viết báo cáo cho FILE", metavar="FILE")
trình phân tích  pháp.add_option("-q", "--quiet",
                  action="store_false", dest="verbose", default=True,
                  help="không in thông báo trạng thái ra thiết bị xuất chuẩn")

(tùy chọn, args) = trình phân tích  pháp.parse_args()

Với một vài dòng mã này, người dùng tập lệnh của bạn giờ đây có thể thực hiện "việc thông thường" trên dòng lệnh, ví dụ:

<yourscript> --file=outfile -q

Khi phân tích cú pháp dòng lệnh, optparse đặt các thuộc tính của đối tượng options được parse_args() trả về dựa trên các giá trị dòng lệnh do người dùng cung cấp. Khi parse_args() trả về từ việc phân tích dòng lệnh này, options.filename sẽ là "outfile"options.verbose sẽ là False. optparse hỗ trợ cả tùy chọn dài và ngắn, cho phép hợp nhất các tùy chọn ngắn với nhau và cho phép các tùy chọn được liên kết với các đối số của chúng theo nhiều cách khác nhau. Do đó, các dòng lệnh sau đều tương đương với ví dụ trên:

<yourscript> -f outfile --quiet
<yourscript> --quiet --file outfile
<yourscript> -q -foutfile
<yourscript> -qfoutfile

Ngoài ra, người dùng có thể chạy một trong các thao tác sau

<yourscript> -h
<yourscript> --help

optparse sẽ in ra bản tóm tắt ngắn gọn về các tùy chọn của tập lệnh của bạn:

Cách sử dụng: <yourscript> [tùy chọn]

Tùy chọn:
  -h, --help hiển thị thông báo trợ giúp này và thoát
  -f FILE, --file=FILE viết báo cáo cho FILE
  -q, --quiet không in thông báo trạng thái ra thiết bị xuất chuẩn

trong đó giá trị của yourscript được xác định trong thời gian chạy (thông thường từ sys.argv[0]).

Nền

optparse được thiết kế rõ ràng để khuyến khích việc tạo ra các chương trình có giao diện dòng lệnh đơn giản tuân theo các quy ước được thiết lập bởi dòng hàm getopt() dành cho các nhà phát triển C. Cuối cùng, nó chỉ hỗ trợ cú pháp dòng lệnh và ngữ nghĩa phổ biến nhất được sử dụng thông thường trong Unix. Nếu bạn không quen với những quy ước này, việc đọc phần này sẽ giúp bạn làm quen với chúng.

Thuật ngữ

lý lẽ

một chuỗi được nhập trên dòng lệnh và được shell chuyển tới execl() hoặc execv(). Trong Python, đối số là các phần tử của sys.argv[1:] (sys.argv[0] là tên của chương trình đang được thực thi). Hệ vỏ Unix cũng sử dụng thuật ngữ "word".

Đôi khi bạn nên thay thế một danh sách đối số khác với sys.argv[1:], vì vậy bạn nên đọc "đối số" là "một phần tử của sys.argv[1:] hoặc của một số danh sách khác được cung cấp để thay thế cho sys.argv[1:]".

tùy chọn

một đối số được sử dụng để cung cấp thêm thông tin nhằm hướng dẫn hoặc tùy chỉnh việc thực hiện chương trình. Có nhiều cú pháp khác nhau cho các tùy chọn; cú pháp Unix truyền thống là dấu gạch nối ("-") theo sau là một chữ cái, ví dụ: -x hoặc -F. Ngoài ra, cú pháp Unix truyền thống cho phép hợp nhất nhiều tùy chọn thành một đối số duy nhất, ví dụ: -x -F tương đương với -xF. Dự án GNU đã giới thiệu --, theo sau là một loạt các từ được phân tách bằng dấu gạch nối, ví dụ: --file hoặc --dry-run. Đây là hai cú pháp tùy chọn duy nhất được cung cấp bởi optparse.

Một số cú pháp tùy chọn khác mà thế giới đã thấy bao gồm:

  • một dấu gạch nối theo sau là một vài chữ cái, ví dụ: -pf (đây là not giống như nhiều tùy chọn được hợp nhất thành một đối số duy nhất)

  • một dấu gạch nối theo sau là cả một từ, ví dụ: -file (cú pháp này về mặt kỹ thuật tương đương với cú pháp trước đó, nhưng chúng thường không xuất hiện trong cùng một chương trình)

  • dấu cộng theo sau là một chữ cái hoặc một vài chữ cái hoặc một từ, ví dụ: +f, +rgb

  • một dấu gạch chéo theo sau là một chữ cái, hoặc một vài chữ cái hoặc một từ, ví dụ: /f, /file

Các cú pháp tùy chọn này không được optparse hỗ trợ và sẽ không bao giờ như vậy. Điều này là có chủ ý: ba cái đầu tiên không chuẩn trên mọi môi trường và cái cuối cùng chỉ có ý nghĩa nếu bạn chỉ nhắm mục tiêu đến Windows hoặc một số nền tảng cũ nhất định (ví dụ: VMS, MS-DOS).

đối số tùy chọn

một đối số theo sau một tùy chọn, được liên kết chặt chẽ với tùy chọn đó và được sử dụng từ danh sách đối số khi có tùy chọn đó. Với optparse, các đối số tùy chọn có thể nằm trong một đối số riêng biệt với tùy chọn của chúng:

-f foo
--file foo

hoặc được bao gồm trong cùng một đối số:

-ffoo
--file=foo

Thông thường, một tùy chọn nhất định có thể nhận một đối số hoặc không. Nhiều người muốn có tính năng "đối số tùy chọn tùy chọn", nghĩa là một số tùy chọn sẽ nhận đối số nếu họ nhìn thấy nó và sẽ không nhận nếu không. Điều này hơi gây tranh cãi vì nó làm cho việc phân tích cú pháp trở nên mơ hồ: nếu -a nhận một đối số tùy chọn và -b hoàn toàn là một tùy chọn khác, thì chúng ta diễn giải -ab như thế nào? Vì sự mơ hồ này nên optparse không hỗ trợ tính năng này.

đối số vị trí

nội dung nào đó còn sót lại trong danh sách đối số sau khi các tùy chọn đã được phân tích cú pháp, tức là sau khi các tùy chọn và đối số của chúng đã được phân tích cú pháp và xóa khỏi danh sách đối số.

tùy chọn bắt buộc

một tùy chọn phải được cung cấp trên dòng lệnh; lưu ý rằng cụm từ "tùy chọn bắt buộc" là tự mâu thuẫn trong tiếng Anh. optparse không ngăn cản bạn triển khai các tùy chọn bắt buộc nhưng cũng không giúp ích gì nhiều cho bạn.

Ví dụ: hãy xem xét dòng lệnh giả định này

prog -v --report report.txt thanh foo

-v--report đều là những lựa chọn. Giả sử --report nhận một đối số thì report.txt là một đối số tùy chọn. foobar là các đối số vị trí.

Tùy chọn cho là gì?

Các tùy chọn được sử dụng để cung cấp thêm thông tin nhằm điều chỉnh hoặc tùy chỉnh việc thực hiện chương trình. Trong trường hợp không rõ ràng, các tùy chọn thường là optional. Một chương trình sẽ có thể chạy tốt mà không cần bất kỳ tùy chọn nào. (Chọn một chương trình ngẫu nhiên từ bộ công cụ Unix hoặc GNU. Nó có thể chạy mà không cần bất kỳ tùy chọn nào mà vẫn hợp lý không? Các ngoại lệ chính là find, tardd---tất cả đều là những đột biến kỳ quặc đã bị chỉ trích một cách chính đáng vì cú pháp không chuẩn và giao diện khó hiểu.)

Rất nhiều người muốn chương trình của họ có "các tùy chọn bắt buộc". Hãy nghĩ về nó. Nếu bắt buộc thì đó là not optional! Nếu có một phần thông tin mà chương trình của bạn thực sự yêu cầu để chạy thành công thì đó chính là mục đích của các đối số vị trí.

Là một ví dụ về thiết kế giao diện dòng lệnh tốt, hãy xem xét tiện ích cp khiêm tốn để sao chép tệp. Sẽ không có ý nghĩa gì nếu cố gắng sao chép các tập tin mà không cung cấp đích đến và ít nhất một nguồn. Do đó, cp sẽ không thành công nếu bạn chạy nó mà không có đối số. Tuy nhiên, nó có cú pháp linh hoạt, hữu ích và không yêu cầu bất kỳ tùy chọn nào:

cp SOURCE DEST
cp SOURCE ... DEST-DIR

Bạn có thể tiến khá xa chỉ với điều đó. Hầu hết các triển khai cp đều cung cấp một loạt tùy chọn để điều chỉnh chính xác cách sao chép tệp: bạn có thể duy trì chế độ và thời gian sửa đổi, tránh đi theo các liên kết tượng trưng, ​​hỏi trước khi ghi đè các tệp hiện có, v.v. Nhưng không điều nào trong số này làm xao lãng nhiệm vụ cốt lõi của cp, đó là sao chép tệp này sang tệp khác hoặc một số tệp vào thư mục khác.

Lập luận vị trí để làm gì?

Đối số vị trí dành cho những mẩu thông tin mà chương trình của bạn chắc chắn yêu cầu để chạy.

Một giao diện người dùng tốt nên có càng ít yêu cầu tuyệt đối càng tốt. Nếu chương trình của bạn yêu cầu 17 mẩu thông tin riêng biệt để chạy thành công thì điều đó không thành vấn đề how bạn nhận được thông tin đó từ người dùng---hầu hết mọi người sẽ bỏ cuộc và bỏ đi trước khi họ chạy chương trình thành công. Điều này áp dụng cho dù giao diện người dùng là dòng lệnh, tệp cấu hình hay GUI: nếu bạn đưa ra nhiều yêu cầu như vậy đối với người dùng của mình, hầu hết họ sẽ từ bỏ.

Tóm lại, hãy cố gắng giảm thiểu lượng thông tin mà người dùng bắt buộc phải cung cấp---sử dụng các giá trị mặc định hợp lý bất cứ khi nào có thể. Tất nhiên, bạn cũng muốn làm cho chương trình của mình linh hoạt một cách hợp lý. Đó là những lựa chọn dành cho. Xin nhắc lại, không thành vấn đề nếu chúng là các mục trong tệp cấu hình, các tiện ích trong hộp thoại "Tùy chọn" của GUI hoặc các tùy chọn dòng lệnh --- bạn triển khai càng nhiều tùy chọn, chương trình của bạn càng linh hoạt hơn và việc triển khai nó càng trở nên phức tạp hơn. Tất nhiên, quá linh hoạt cũng có những hạn chế; quá nhiều tùy chọn có thể khiến người dùng choáng ngợp và khiến mã của bạn khó bảo trì hơn nhiều.

Hướng dẫn

Mặc dù optparse khá linh hoạt và mạnh mẽ nhưng nó cũng dễ sử dụng trong hầu hết các trường hợp. Phần này bao gồm các mẫu mã phổ biến cho bất kỳ chương trình dựa trên optparse- nào.

Trước tiên, bạn cần nhập lớp OptionParser; sau đó, ngay từ đầu chương trình chính, hãy tạo một phiên bản OptionParser:

từ nhập optparse OptionParser
...
trình phân tích  pháp = OptionParser()

Sau đó, bạn có thể bắt đầu xác định các tùy chọn. Cú pháp cơ bản là:

trình phân tích  pháp.add_option(opt_str, ...,
                  attr=giá trị, ...)

Mỗi tùy chọn có một hoặc nhiều chuỗi tùy chọn, chẳng hạn như -f hoặc --file và một số thuộc tính tùy chọn cho optparse biết điều gì sẽ xảy ra và phải làm gì khi gặp tùy chọn đó trên dòng lệnh.

Thông thường, mỗi tùy chọn sẽ có một chuỗi tùy chọn ngắn và một chuỗi tùy chọn dài, ví dụ::

Parser.add_option("-f", "--file", ...)

Bạn có thể tự do xác định bao nhiêu chuỗi tùy chọn ngắn và bao nhiêu chuỗi tùy chọn dài tùy thích (bao gồm cả số 0), miễn là tổng thể có ít nhất một chuỗi tùy chọn.

Các chuỗi tùy chọn được chuyển đến OptionParser.add_option() thực sự là các nhãn cho tùy chọn được xác định bởi lệnh gọi đó. Để ngắn gọn, chúng tôi sẽ thường xuyên đề cập đến encountering an option trên dòng lệnh; trên thực tế, optparse gặp option strings và tìm kiếm các lựa chọn từ họ.

Khi tất cả các tùy chọn của bạn đã được xác định, hãy hướng dẫn optparse phân tích dòng lệnh của chương trình của bạn

(tùy chọn, args) = trình phân tích  pháp.parse_args()

(Nếu muốn, bạn có thể chuyển danh sách đối số tùy chỉnh cho parse_args(), nhưng điều đó hiếm khi cần thiết: theo mặc định, nó sử dụng sys.argv[1:].)

parse_args() trả về hai giá trị:

  • options, một đối tượng chứa các giá trị cho tất cả các tùy chọn của bạn---ví dụ: nếu --file nhận một đối số chuỗi đơn thì options.file sẽ là tên tệp do người dùng cung cấp hoặc None nếu người dùng không cung cấp tùy chọn đó

  • args, danh sách các đối số vị trí còn sót lại sau khi phân tích các tùy chọn

Phần hướng dẫn này chỉ bao gồm bốn thuộc tính tùy chọn quan trọng nhất: action, type, dest (destination) và help. Trong số này, action là cơ bản nhất.

Hiểu hành động tùy chọn

Các hành động sẽ cho optparse biết phải làm gì khi gặp một tùy chọn trên dòng lệnh. Có một tập hợp hành động cố định được mã hóa cứng thành optparse; thêm hành động mới là chủ đề nâng cao được đề cập trong phần Mở rộng optparse. Hầu hết các hành động đều yêu cầu optparse lưu trữ một giá trị trong một số biến --- ví dụ: lấy một chuỗi từ dòng lệnh và lưu nó vào thuộc tính của options.

Nếu bạn không chỉ định hành động tùy chọn, optparse sẽ mặc định là store.

Hành động của cửa hàng

Hành động tùy chọn phổ biến nhất là store, yêu cầu optparse lấy đối số tiếp theo (hoặc phần còn lại của đối số hiện tại), đảm bảo rằng đối số đó thuộc đúng loại và lưu nó vào đích bạn đã chọn.

Ví dụ:

trình phân tích  pháp.add_option("-f", "--file",
                  action="store", type="string", dest="filename")

Bây giờ hãy tạo một dòng lệnh giả và yêu cầu optparse phân tích nó

args = ["-f", "foo.txt"]
(tùy chọn, args) = parser.parse_args(args)

Khi optparse nhìn thấy chuỗi tùy chọn -f, nó sẽ sử dụng đối số tiếp theo, foo.txt và lưu nó trong options.filename. Vì vậy, sau lệnh gọi tới parse_args(), options.filename"foo.txt".

Một số loại tùy chọn khác được optparse hỗ trợ là intfloat. Đây là một tùy chọn yêu cầu một đối số nguyên:

parser.add_option("-n", type="int", dest="num")

Lưu ý rằng tùy chọn này không có chuỗi tùy chọn dài, điều này hoàn toàn có thể chấp nhận được. Ngoài ra, không có hành động rõ ràng nào vì mặc định là store.

Hãy phân tích một dòng lệnh giả khác. Lần này, chúng ta sẽ đặt đối số tùy chọn đối lập với tùy chọn: vì -n42 (một đối số) tương đương với -n 42 (hai đối số), nên mã

(tùy chọn, args) = Parser.parse_args(["-n42"])
in(options.num)

sẽ in 42.

Nếu bạn không chỉ định loại, optparse sẽ giả sử string. Kết hợp với thực tế là hành động mặc định là store, điều đó có nghĩa là ví dụ đầu tiên của chúng ta có thể ngắn hơn rất nhiều:

parser.add_option("-f", "--file", dest="filename")

Nếu bạn không cung cấp đích, optparse sẽ tìm ra một mặc định hợp lý từ các chuỗi tùy chọn: nếu chuỗi tùy chọn dài đầu tiên là --foo-bar thì đích mặc định là foo_bar. Nếu không có chuỗi tùy chọn dài, optparse sẽ xem chuỗi tùy chọn ngắn đầu tiên: đích mặc định cho -ff.

optparse cũng bao gồm loại complex tích hợp sẵn. Việc thêm các loại được đề cập trong phần Mở rộng optparse.

Xử lý các tùy chọn boolean (cờ)

Các tùy chọn gắn cờ --- đặt một biến thành đúng hoặc sai khi nhìn thấy một tùy chọn cụ thể --- khá phổ biến. optparse hỗ trợ chúng bằng hai hành động riêng biệt là store_truestore_false. Ví dụ: bạn có thể có cờ verbose được bật bằng -v và tắt bằng -q:

parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose")

Ở đây chúng ta có hai lựa chọn khác nhau với cùng một đích đến, điều này hoàn toàn ổn. (Điều đó chỉ có nghĩa là bạn phải cẩn thận một chút khi đặt giá trị mặc định---xem bên dưới.)

Khi optparse gặp -v trên dòng lệnh, nó đặt options.verbose thành True; khi gặp -q, options.verbose được đặt thành False.

Các hành động khác

Một số hành động khác được optparse hỗ trợ là:

"store_const"

lưu trữ một giá trị không đổi, được đặt trước qua Option.const

"append"

nối đối số của tùy chọn này vào danh sách

"count"

tăng bộ đếm lên một

"callback"

gọi một hàm được chỉ định

Chúng được trình bày trong phần Hướng dẫn tham khảo và phần Tùy chọn gọi lại.

Giá trị mặc định

Tất cả các ví dụ trên đều liên quan đến việc thiết lập một số biến ("đích") khi nhìn thấy các tùy chọn dòng lệnh nhất định. Điều gì xảy ra nếu những lựa chọn đó không bao giờ được nhìn thấy? Vì chúng tôi không cung cấp bất kỳ giá trị mặc định nào nên tất cả chúng đều được đặt thành None. Điều này thường ổn nhưng đôi khi bạn muốn kiểm soát nhiều hơn. optparse cho phép bạn cung cấp giá trị mặc định cho từng đích, giá trị này được chỉ định trước khi dòng lệnh được phân tích cú pháp.

Đầu tiên, hãy xem xét ví dụ dài dòng/im lặng. Nếu chúng ta muốn optparse đặt verbose thành True trừ khi -q được nhìn thấy, thì chúng ta có thể làm điều này:

parser.add_option("-v", action="store_true", dest="verbose", default=True)
parser.add_option("-q", action="store_false", dest="verbose")

Vì các giá trị mặc định áp dụng cho destination thay vì bất kỳ tùy chọn cụ thể nào và hai tùy chọn này có cùng đích đến, nên điều này hoàn toàn tương đương:

parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose", default=True)

Hãy xem xét điều này:

parser.add_option("-v", action="store_true", dest="verbose", default=False)
parser.add_option("-q", action="store_false", dest="verbose", default=True)

Một lần nữa, giá trị mặc định cho verbose sẽ là True: giá trị mặc định cuối cùng được cung cấp cho bất kỳ đích cụ thể nào là giá trị được tính.

Một cách rõ ràng hơn để chỉ định các giá trị mặc định là phương thức set_defaults() của OptionParser, bạn có thể gọi bất kỳ lúc nào trước khi gọi parse_args():

trình phân tích  pháp.set_defaults(verbose=True)
trình phân tích  pháp.add_option(...)
(tùy chọn, args) = trình phân tích  pháp.parse_args()

Như trước đây, giá trị cuối cùng được chỉ định cho đích tùy chọn nhất định là giá trị được tính. Để rõ ràng, hãy thử sử dụng phương pháp này hoặc phương pháp khác để đặt giá trị mặc định, không phải cả hai.

Tạo trợ giúp

Khả năng tự động tạo văn bản trợ giúp và cách sử dụng của optparse rất hữu ích để tạo giao diện dòng lệnh thân thiện với người dùng. Tất cả những gì bạn phải làm là cung cấp giá trị help cho mỗi tùy chọn và tùy chọn một thông báo sử dụng ngắn cho toàn bộ chương trình của bạn. Đây là OptionParser có các tùy chọn (được ghi lại) thân thiện với người dùng

cách sử dụng = "cách sử dụng: %prog [tùy chọn] arg1 arg2"
trình phân tích  pháp = OptionParser(cách sử dụng=cách sử dụng)
trình phân tích  pháp.add_option("-v", "--verbose",
                  action="store_true", dest="verbose", default=True,
                  help="gây ra nhiều tiếng ồn [mặc định]")
trình phân tích  pháp.add_option("-q", "--quiet",
                  hành động="store_false", dest="verbose",
                  help="im lặng chút đi (Tôi đang săn thỏ)")
trình phân tích  pháp.add_option("-f", "--filename",
                  metavar="FILE", help="ghi đầu ra vào FILE")
trình phân tích  pháp.add_option("-m", "--mode",
                  mặc định="trung gian",
                  help="chế độ tương tác: người mới, trung cấp, "
                       "hoặc chuyên gia [mặc định: %mặc định]")

Nếu optparse gặp -h hoặc --help trên dòng lệnh hoặc nếu bạn chỉ gọi parser.print_help(), nó sẽ in thông tin sau ra đầu ra tiêu chuẩn:

Cách sử dụng: <yourscript> [tùy chọn] arg1 arg2

Tùy chọn:
  -h, --help hiển thị thông báo trợ giúp này và thoát
  -v, --verbose tạo ra nhiều tiếng ồn [mặc định]
  -q, --quiet im lặng đi (Tôi đang săn thỏ)
  -f FILE, --filename=FILE
                        ghi đầu ra vào FILE
  -m MODE, --mode=MODE chế độ tương tác: người mới, người trung cấp hoặc
                        chuyên gia [mặc định: trung cấp]

(Nếu đầu ra trợ giúp được kích hoạt bởi tùy chọn trợ giúp, optparse sẽ thoát sau khi in văn bản trợ giúp.)

Có rất nhiều điều đang diễn ra ở đây để giúp optparse tạo ra thông báo trợ giúp tốt nhất có thể:

  • tập lệnh xác định thông báo sử dụng của riêng nó:

    cách sử dụng = "cách sử dụng: %prog [tùy chọn] arg1 arg2"
    

    optparse mở rộng %prog trong chuỗi sử dụng thành tên của chương trình hiện tại, tức là os.path.basename(sys.argv[0]). Sau đó, chuỗi mở rộng sẽ được in trước khi có trợ giúp tùy chọn chi tiết.

    Nếu bạn không cung cấp chuỗi sử dụng, optparse sẽ sử dụng một giá trị mặc định nhạt nhẽo nhưng hợp lý: "Usage: %prog [options]", điều này sẽ ổn nếu tập lệnh của bạn không nhận bất kỳ đối số vị trí nào.

  • mọi tùy chọn đều xác định một chuỗi trợ giúp và không phải lo lắng về việc ngắt dòng---optparse đảm nhiệm việc gói các dòng và làm cho đầu ra trợ giúp trông đẹp mắt.

  • các tùy chọn nhận giá trị cho biết thực tế này trong thông báo trợ giúp được tạo tự động, ví dụ: cho tùy chọn "chế độ":

    -m MODE, --mode=MODE
    

    Ở đây, "MODE" được gọi là biến meta: nó đại diện cho đối số mà người dùng dự kiến sẽ cung cấp cho -m/--mode. Theo mặc định, optparse chuyển đổi tên biến đích thành chữ hoa và sử dụng tên đó cho biến meta. Đôi khi, đó không phải là điều bạn muốn---ví dụ: tùy chọn --filename đặt metavar="FILE" một cách rõ ràng, dẫn đến mô tả tùy chọn được tạo tự động này:

    -f FILE, --filename=FILE
    

    Tuy nhiên, điều này quan trọng không chỉ để tiết kiệm dung lượng: văn bản trợ giúp được viết thủ công sử dụng biến meta FILE để gợi ý cho người dùng rằng có mối liên hệ giữa cú pháp bán chính thức -f FILE và mô tả ngữ nghĩa không chính thức "ghi đầu ra vào FILE". Đây là một cách đơn giản nhưng hiệu quả để làm cho văn bản trợ giúp của bạn rõ ràng hơn và hữu ích hơn cho người dùng cuối.

  • các tùy chọn có giá trị mặc định có thể bao gồm %default trong chuỗi trợ giúp---optparse sẽ thay thế nó bằng str() giá trị mặc định của tùy chọn. Nếu một tùy chọn không có giá trị mặc định (hoặc giá trị mặc định là None), %default sẽ mở rộng thành none.

Tùy chọn nhóm

Khi xử lý nhiều tùy chọn, sẽ thuận tiện hơn khi nhóm các tùy chọn này để có kết quả trợ giúp tốt hơn. Một OptionParser có thể chứa một số nhóm tùy chọn, mỗi nhóm có thể chứa một số tùy chọn.

Một nhóm tùy chọn thu được bằng cách sử dụng lớp OptionGroup:

class optparse.OptionGroup(parser, title, description=None)

ở đâu

  • trình phân tích cú pháp là phiên bản OptionParser mà nhóm sẽ được chèn vào

  • title là tên nhóm

  • mô tả, tùy chọn, là một mô tả dài về nhóm

OptionGroup kế thừa từ OptionContainer (như OptionParser) và do đó phương thức add_option() có thể được sử dụng để thêm tùy chọn vào nhóm.

Khi tất cả các tùy chọn được khai báo, sử dụng phương thức OptionParser add_option_group(), nhóm sẽ được thêm vào trình phân tích cú pháp được xác định trước đó.

Tiếp tục với trình phân tích cú pháp được xác định trong phần trước, việc thêm OptionGroup vào trình phân tích cú pháp thật dễ dàng:

group = OptionGroup(trình phân tích  pháp, "Tùy chọn nguy hiểm",
                    "Thận trọng: bạn phải tự chịu rủi ro khi sử dụng các tùy chọn này."
                    "Người ta tin rằng một số trong số chúng đã cắn.")
group.add_option("-g", action="store_true", help="Tùy chọn nhóm.")
trình phân tích  pháp.add_option_group(nhóm)

Điều này sẽ dẫn đến kết quả trợ giúp sau:

Cách sử dụng: <yourscript> [tùy chọn] arg1 arg2

Tùy chọn:
  -h, --help hiển thị thông báo trợ giúp này và thoát
  -v, --verbose tạo ra nhiều tiếng ồn [mặc định]
  -q, --quiet im lặng đi (Tôi đang săn thỏ)
  -f FILE, --filename=FILE
                        ghi đầu ra vào FILE
  -m MODE, --mode=MODE chế độ tương tác: người mới, người trung cấp hoặc
                        chuyên gia [mặc định: trung cấp]

  Tùy chọn nguy hiểm:
    Thận trọng: sử dụng các tùy chọn này có nguy cơ của riêng bạn.  Người ta tin rằng một số
    trong số chúng cắn.

    -g Tùy chọn nhóm.

Một ví dụ đầy đủ hơn một chút có thể liên quan đến việc sử dụng nhiều hơn một nhóm: vẫn mở rộng ví dụ trước:

group = OptionGroup(trình phân tích  pháp, "Tùy chọn nguy hiểm",
                    "Thận trọng: bạn phải tự chịu rủi ro khi sử dụng các tùy chọn này."
                    "Người ta tin rằng một số trong số chúng đã cắn.")
group.add_option("-g", action="store_true", help="Tùy chọn nhóm.")
trình phân tích  pháp.add_option_group(nhóm)

group = OptionGroup(trình phân tích  pháp, "Tùy chọn gỡ lỗi")
group.add_option("-d", "--debug", action="store_true",
                 help="In thông tin gỡ lỗi")
group.add_option("-s", "--sql", action="store_true",
                 help="In tất cả các câu lệnh SQL đã thực thi")
group.add_option("-e", action="store_true", help="In mọi hành động đã thực hiện")
trình phân tích  pháp.add_option_group(nhóm)

dẫn đến kết quả đầu ra sau:

Cách sử dụng: <yourscript> [tùy chọn] arg1 arg2

Tùy chọn:
  -h, --help hiển thị thông báo trợ giúp này và thoát
  -v, --verbose tạo ra nhiều tiếng ồn [mặc định]
  -q, --quiet im lặng đi (Tôi đang săn thỏ)
  -f FILE, --filename=FILE
                        ghi đầu ra vào FILE
  -m MODE, --mode=MODE chế độ tương tác: người mới, người trung cấp hoặc chuyên gia
                        [mặc định: trung gian]

  Tùy chọn nguy hiểm:
    Thận trọng: sử dụng các tùy chọn này có nguy cơ của riêng bạn.  Người ta tin rằng một số
    trong số chúng cắn.

    -g Tùy chọn nhóm.

  Tùy chọn gỡ lỗi:
    -d, --debug In thông tin gỡ lỗi
    -s, --sql In tất cả các câu lệnh SQL được thực thi
    -e In mọi hành động được thực hiện

Một phương pháp thú vị khác, đặc biệt khi làm việc theo chương trình với các nhóm tùy chọn là:

OptionParser.get_option_group(opt_str)

Trả về OptionGroup chứa chuỗi tùy chọn ngắn hoặc dài opt_str (ví dụ: '-o' hoặc '--option'). Nếu không có OptionGroup như vậy, hãy trả về None.

In chuỗi phiên bản

Tương tự như chuỗi sử dụng ngắn gọn, optparse cũng có thể in chuỗi phiên bản cho chương trình của bạn. Bạn phải cung cấp chuỗi làm đối số version cho OptionParser:

trình phân tích  pháp = OptionParser(usage="%prog [-f] [-q]", version="%prog 1.0")

%prog được mở rộng giống như trong usage. Ngoài ra, version có thể chứa bất cứ thứ gì bạn thích. Khi bạn cung cấp nó, optparse sẽ tự động thêm tùy chọn --version vào trình phân tích cú pháp của bạn. Nếu nó gặp tùy chọn này trên dòng lệnh, nó sẽ mở rộng chuỗi version của bạn (bằng cách thay thế %prog), in nó ra thiết bị xuất chuẩn và thoát.

Ví dụ: nếu tập lệnh của bạn có tên là /usr/bin/foo:

$ /usr/bin/foo --version
foo 1.0

Hai phương pháp sau đây có thể được sử dụng để in và lấy chuỗi version:

OptionParser.print_version(file=None)

In thông báo phiên bản cho chương trình hiện tại (self.version) thành file (thiết bị xuất chuẩn mặc định). Giống như print_usage(), bất kỳ sự xuất hiện nào của %prog trong self.version đều được thay thế bằng tên của chương trình hiện tại. Không có gì nếu self.version trống hoặc không xác định.

OptionParser.get_version()

Tương tự như print_version() nhưng trả về chuỗi phiên bản thay vì in ra.

Cách optparse xử lý lỗi

Có hai loại lỗi lớn mà optparse phải lo lắng: lỗi lập trình viên và lỗi người dùng. Lỗi lập trình viên thường là các lệnh gọi sai tới OptionParser.add_option(), ví dụ: chuỗi tùy chọn không hợp lệ, thuộc tính tùy chọn không xác định, thuộc tính tùy chọn bị thiếu, v.v. Chúng được xử lý theo cách thông thường: đưa ra một ngoại lệ (optparse.OptionError hoặc TypeError) và khiến chương trình gặp sự cố.

Xử lý lỗi của người dùng quan trọng hơn nhiều vì chúng chắc chắn sẽ xảy ra cho dù mã của bạn có ổn định đến đâu. optparse có thể tự động phát hiện một số lỗi của người dùng, chẳng hạn như đối số tùy chọn không hợp lệ (chuyển -n 4x trong đó -n nhận đối số nguyên), thiếu đối số (-n ở cuối dòng lệnh, trong đó -n nhận đối số thuộc bất kỳ loại nào). Ngoài ra, bạn có thể gọi OptionParser.error() để báo hiệu tình trạng lỗi do ứng dụng xác định

(tùy chọn, args) = trình phân tích  pháp.parse_args()
...
nếu tùy chọn.a  tùy chọn.b:
    Parser.error("các tùy chọn -a và -b loại trừ lẫn nhau")

Trong cả hai trường hợp, optparse xử lý lỗi theo cùng một cách: nó in thông báo sử dụng của chương trình và thông báo lỗi thành lỗi tiêu chuẩn và thoát với trạng thái lỗi 2.

Hãy xem xét ví dụ đầu tiên ở trên, trong đó người dùng chuyển 4x đến một tùy chọn lấy số nguyên:

$ /usr/bin/foo -n 4x
Cách sử dụng: foo [tùy chọn]

foo: error: option -n: giá trị nguyên không hợp lệ: '4x'

Hoặc, khi người dùng không chuyển được một giá trị nào:

$ /usr/bin/foo -n
Cách sử dụng: foo [tùy chọn]

foo: error: tùy chọn -n yêu cầu một đối số

optparse-thông báo lỗi được tạo ra, hãy luôn đề cập đến tùy chọn liên quan đến lỗi; hãy nhớ thực hiện tương tự khi gọi OptionParser.error() từ mã ứng dụng của bạn.

Nếu hành vi xử lý lỗi mặc định của optparse không phù hợp với nhu cầu của bạn, bạn sẽ cần phải phân lớp OptionParser và ghi đè các phương thức exit() và/hoặc error() của nó.

Đặt tất cả lại với nhau

Đây là các tập lệnh dựa trên optparse- thường trông như thế nào:

từ nhập optparse OptionParser
...
chắc chắn chính():
    cách sử dụng = "cách sử dụng:% prog [tùy chọn] arg"
    trình phân tích  pháp = OptionParser(cách sử dụng)
    parser.add_option("-f", "--file", dest="filename",
                      help="đọc dữ liệu từ FILENAME")
    trình phân tích  pháp.add_option("-v", "--verbose",
                      hành động="store_true", dest="verbose")
    trình phân tích  pháp.add_option("-q", "--quiet",
                      hành động="store_false", dest="verbose")
    ...
    (tùy chọn, args) = trình phân tích  pháp.parse_args()
    nếu len(args) != 1:
        Parser.error("số lượng đối số không chính xác")
    nếu tùy chọn.verbose:
        print("Đang đọc %s..." % options.filename)
    ...

nếu __name__ == "__main__":
    chính()

Hướng dẫn tham khảo

Tạo trình phân tích cú pháp

Bước đầu tiên khi sử dụng optparse là tạo một phiên bản OptionParser.

class optparse.OptionParser(...)

Hàm tạo OptionParser không có đối số bắt buộc nhưng có một số đối số từ khóa tùy chọn. Bạn phải luôn chuyển chúng dưới dạng đối số từ khóa, tức là không dựa vào thứ tự khai báo đối số.

usage (mặc định: "%prog [options]")

Bản tóm tắt sử dụng để in khi chương trình của bạn chạy không chính xác hoặc có tùy chọn trợ giúp. Khi optparse in chuỗi sử dụng, nó sẽ mở rộng %prog thành os.path.basename(sys.argv[0]) (hoặc thành prog nếu bạn chuyển đối số từ khóa đó). Để chặn thông báo sử dụng, hãy chuyển giá trị đặc biệt optparse.SUPPRESS_USAGE.

option_list (mặc định: [])

Danh sách các đối tượng Tùy chọn để điền vào trình phân tích cú pháp. Các tùy chọn trong option_list được thêm vào sau bất kỳ tùy chọn nào trong standard_option_list (thuộc tính lớp có thể được đặt bởi các lớp con OptionParser), nhưng trước bất kỳ phiên bản hoặc tùy chọn trợ giúp nào. Không dùng nữa; thay vào đó hãy sử dụng add_option() sau khi tạo trình phân tích cú pháp.

option_class (mặc định: optparse.Option)

Lớp sử dụng khi thêm tùy chọn vào trình phân tích cú pháp trong add_option().

version (mặc định: None)

Chuỗi phiên bản để in khi người dùng cung cấp tùy chọn phiên bản. Nếu bạn cung cấp giá trị thực cho version, optparse sẽ tự động thêm tùy chọn phiên bản với chuỗi tùy chọn duy nhất --version. Chuỗi con %prog được mở rộng giống như chuỗi usage.

conflict_handler (mặc định: "error")

Chỉ định những việc cần làm khi các tùy chọn có chuỗi tùy chọn xung đột được thêm vào trình phân tích cú pháp; xem phần Xung đột giữa các lựa chọn.

description (mặc định: None)

Một đoạn văn bản cung cấp một cái nhìn tổng quan ngắn gọn về chương trình của bạn. optparse định dạng lại đoạn này để vừa với chiều rộng của thiết bị đầu cuối hiện tại và in nó khi người dùng yêu cầu trợ giúp (sau usage, nhưng trước danh sách tùy chọn).

formatter (mặc định: IndentedHelpFormatter mới)

Một phiên bản optparse.HelpFormatter sẽ được sử dụng để in văn bản trợ giúp. optparse cung cấp hai lớp cụ thể cho mục đích này: IndentedHelpFormatter và TitledHelpFormatter.

add_help_option (mặc định: True)

Nếu đúng, optparse sẽ thêm tùy chọn trợ giúp (với chuỗi tùy chọn -h--help) vào trình phân tích cú pháp.

prog

Chuỗi sử dụng khi mở rộng %prog trong usageversion thay vì os.path.basename(sys.argv[0]).

epilog (mặc định: None)

Một đoạn văn bản trợ giúp sẽ được in sau tùy chọn trợ giúp.

Điền trình phân tích cú pháp

Có một số cách để đưa vào trình phân tích cú pháp các tùy chọn. Cách tốt nhất là sử dụng OptionParser.add_option(), như được trình bày trong phần Hướng dẫn. add_option() có thể được gọi theo một trong hai cách:

  • chuyển cho nó một phiên bản Tùy chọn (được trả về bởi make_option())

  • chuyển cho nó bất kỳ sự kết hợp nào giữa các đối số vị trí và từ khóa được chấp nhận bởi make_option() (tức là đối với hàm tạo Tùy chọn) và nó sẽ tạo phiên bản Tùy chọn cho bạn

Cách khác là chuyển danh sách các phiên bản Tùy chọn được tạo sẵn cho hàm tạo OptionParser, như trong

tùy chọn_list = [
    make_option("-f", "--filename",
                action="store", type="string", dest="filename"),
    make_option("-q", "--quiet",
                hành động="store_false", dest="verbose"),
    ]
trình phân tích  pháp = OptionParser(option_list=option_list)

(make_option() là một hàm gốc để tạo các phiên bản Tùy chọn; hiện tại nó là bí danh của hàm tạo Tùy chọn. Phiên bản trong tương lai của optparse có thể chia Tùy chọn thành nhiều lớp và make_option() sẽ chọn đúng lớp để khởi tạo. Không khởi tạo Tùy chọn trực tiếp.)

Xác định các tùy chọn

Mỗi phiên bản Tùy chọn đại diện cho một tập hợp các chuỗi tùy chọn dòng lệnh đồng nghĩa, ví dụ: -f--file. Bạn có thể chỉ định số lượng chuỗi tùy chọn ngắn hoặc dài bất kỳ, nhưng bạn phải chỉ định ít nhất một chuỗi tùy chọn tổng thể.

Cách chuẩn để tạo một phiên bản Option là sử dụng phương thức add_option() của OptionParser.

OptionParser.add_option(option)
OptionParser.add_option(*opt_str, attr=value, ...)

Để xác định một tùy chọn chỉ có một chuỗi tùy chọn ngắn

parser.add_option("-f", attr=value, ...)

Và để xác định một tùy chọn chỉ có một chuỗi tùy chọn dài

parser.add_option("--foo", attr=value, ...)

Các đối số từ khóa xác định các thuộc tính của đối tượng Tùy chọn mới. Thuộc tính tùy chọn quan trọng nhất là action và nó quyết định phần lớn những thuộc tính nào khác có liên quan hoặc bắt buộc. Nếu bạn chuyển các thuộc tính tùy chọn không liên quan hoặc không chuyển các thuộc tính bắt buộc, optparse sẽ đưa ra một ngoại lệ OptionError giải thích lỗi của bạn.

action của một tùy chọn xác định optparse sẽ làm gì khi gặp tùy chọn này trên dòng lệnh. Các hành động tùy chọn tiêu chuẩn được mã hóa cứng vào optparse là:

"store"

lưu trữ đối số của tùy chọn này (mặc định)

"store_const"

lưu trữ một giá trị không đổi, được đặt trước qua Option.const

"store_true"

cửa hàng True

"store_false"

cửa hàng False

"append"

nối đối số của tùy chọn này vào danh sách

"append_const"

thêm một giá trị không đổi vào danh sách, được đặt trước qua Option.const

"count"

tăng bộ đếm lên một

"callback"

gọi một hàm được chỉ định

"help"

in thông báo sử dụng bao gồm tất cả các tùy chọn và tài liệu cho chúng

(Nếu bạn không cung cấp một hành động thì mặc định là "store". Đối với hành động này, bạn cũng có thể cung cấp các thuộc tính tùy chọn typedest; xem Hành động tùy chọn tiêu chuẩn.)

Như bạn có thể thấy, hầu hết các hành động đều liên quan đến việc lưu trữ hoặc cập nhật một giá trị ở đâu đó. optparse luôn tạo một đối tượng đặc biệt cho việc này, thường được gọi là options, một phiên bản của optparse.Values.

class optparse.Values

Một đối tượng chứa tên và giá trị đối số được phân tích cú pháp làm thuộc tính. Thường được tạo bằng cách gọi khi gọi OptionParser.parse_args() và có thể bị ghi đè bởi một lớp con tùy chỉnh được truyền cho đối số values của OptionParser.parse_args() (như được mô tả trong Phân tích đối số).

Các đối số tùy chọn (và nhiều giá trị khác) được lưu trữ dưới dạng thuộc tính của đối tượng này, theo thuộc tính tùy chọn dest (đích).

Ví dụ: khi bạn gọi

trình phân tích  pháp.parse_args()

một trong những điều đầu tiên optparse thực hiện là tạo đối tượng options:

tùy chọn = Giá trị()

Nếu một trong các tùy chọn trong trình phân tích cú pháp này được xác định bằng

Parser.add_option("-f", "--file", action="store", type="string", dest="filename")

và dòng lệnh được phân tích cú pháp bao gồm bất kỳ thông tin nào sau đây

-ffoo
-f foo
--file=foo
--file foo

thì optparse, khi nhìn thấy tùy chọn này, sẽ thực hiện tương đương với

options.filename = "foo"

Các thuộc tính tùy chọn typedest gần như quan trọng như action, nhưng action là thuộc tính duy nhất có ý nghĩa đối với các tùy chọn all.

Thuộc tính tùy chọn

class optparse.Option

Một đối số dòng lệnh duy nhất, với các thuộc tính khác nhau được truyền từ khóa tới hàm tạo. Thường được tạo bằng OptionParser.add_option() chứ không phải trực tiếp và có thể được ghi đè bởi một lớp tùy chỉnh thông qua đối số option_class thành OptionParser.

Các thuộc tính tùy chọn sau đây có thể được chuyển dưới dạng đối số từ khóa cho OptionParser.add_option(). Nếu bạn chuyển một thuộc tính tùy chọn không liên quan đến một tùy chọn cụ thể hoặc không chuyển thuộc tính tùy chọn bắt buộc, optparse sẽ tăng OptionError.

Option.action

(mặc định: "store")

Xác định hành vi của optparse khi tùy chọn này được nhìn thấy trên dòng lệnh; các tùy chọn có sẵn được ghi lại here.

Option.type

(mặc định: "string")

Loại đối số mà tùy chọn này mong đợi (ví dụ: "string" hoặc "int"); các loại tùy chọn có sẵn được ghi lại here.

Option.dest

(mặc định: xuất phát từ chuỗi tùy chọn)

Nếu hành động của tùy chọn ngụ ý ghi hoặc sửa đổi một giá trị ở đâu đó, điều này sẽ cho optparse biết nơi ghi giá trị đó: dest đặt tên cho một thuộc tính của đối tượng optionsoptparse xây dựng khi nó phân tích dòng lệnh.

Option.default

Giá trị sử dụng cho đích của tùy chọn này nếu tùy chọn này không được nhìn thấy trên dòng lệnh. Xem thêm OptionParser.set_defaults().

Option.nargs

(mặc định: 1)

Cần sử dụng bao nhiêu đối số thuộc loại type khi nhìn thấy tùy chọn này. Nếu > 1, optparse sẽ lưu trữ một bộ giá trị vào dest.

Option.const

Đối với các hành động lưu trữ một giá trị không đổi, giá trị không đổi cần lưu trữ.

Option.choices

Đối với các tùy chọn loại "choice", danh sách các chuỗi mà người dùng có thể chọn.

Option.callback

Đối với các tùy chọn có hành động "callback", có thể gọi khi tùy chọn này được nhìn thấy. Xem phần Tùy chọn gọi lại để biết chi tiết về các đối số được truyền cho đối tượng có thể gọi được.

Option.callback_args
Option.callback_kwargs

Các đối số từ khóa và vị trí bổ sung cần chuyển tới callback sau bốn đối số gọi lại tiêu chuẩn.

Option.help

Văn bản trợ giúp in cho tùy chọn này khi liệt kê tất cả các tùy chọn có sẵn sau khi người dùng cung cấp tùy chọn help (chẳng hạn như --help). Nếu không có văn bản trợ giúp nào được cung cấp, tùy chọn sẽ được liệt kê mà không có văn bản trợ giúp. Để ẩn tùy chọn này, hãy sử dụng giá trị đặc biệt optparse.SUPPRESS_HELP.

Option.metavar

(mặc định: xuất phát từ chuỗi tùy chọn)

Thay thế cho (các) đối số tùy chọn để sử dụng khi in văn bản trợ giúp. Xem phần Hướng dẫn để biết ví dụ.

Hành động tùy chọn tiêu chuẩn

Các hành động tùy chọn khác nhau đều có các yêu cầu và tác dụng hơi khác nhau. Hầu hết các hành động đều có một số thuộc tính tùy chọn liên quan mà bạn có thể chỉ định để hướng dẫn hành vi của optparse; một số có các thuộc tính bắt buộc mà bạn phải chỉ định cho bất kỳ tùy chọn nào sử dụng hành động đó.

  • "store" [có liên quan: type, dest, nargs, choices]

    Theo sau tùy chọn này phải là một đối số, đối số này được chuyển đổi thành giá trị theo type và được lưu trữ trong dest. Nếu nargs > 1, nhiều đối số sẽ được sử dụng từ dòng lệnh; tất cả sẽ được chuyển đổi theo type và được lưu trữ thành dest dưới dạng tuple. Xem phần Các loại tùy chọn tiêu chuẩn.

    Nếu choices được cung cấp (danh sách hoặc bộ chuỗi), loại mặc định là "choice".

    Nếu type không được cung cấp, nó sẽ mặc định là "string".

    Nếu dest không được cung cấp, optparse sẽ lấy đích từ chuỗi tùy chọn dài đầu tiên (ví dụ: --foo-bar ngụ ý foo_bar). Nếu không có chuỗi tùy chọn dài, optparse sẽ lấy đích từ chuỗi tùy chọn ngắn đầu tiên (ví dụ: -f ngụ ý f).

    Ví dụ:

    trình phân tích  pháp.add_option("-f")
    parser.add_option("-p", type="float", nargs=3, dest="point")
    

    Khi nó phân tích dòng lệnh

    -f foo.txt -p 1 -3.5 4 -fbar.txt
    

    optparse sẽ đặt

    tùy chọn.f = "foo.txt"
    tùy chọn.point = (1.0, -3.5, 4.0)
    tùy chọn.f = "bar.txt"
    
  • "store_const" [bắt buộc: const; có liên quan: dest]

    Giá trị const được lưu trữ trong dest.

    Ví dụ:

    trình phân tích  pháp.add_option("-q", "--quiet",
                      hành động="store_const", const=0, dest="verbose")
    trình phân tích  pháp.add_option("-v", "--verbose",
                      hành động="store_const", const=1, dest="verbose")
    parser.add_option("--noisy",
                      hành động="store_const", const=2, dest="verbose")
    

    Nếu --noisy được nhìn thấy, optparse sẽ đặt

    tùy chọn.verbose = 2
    
  • "store_true" [có liên quan: dest]

    Một trường hợp đặc biệt của "store_const" lưu trữ True đến dest.

  • "store_false" [có liên quan: dest]

    Giống như "store_true" nhưng lưu trữ False.

    Ví dụ:

    parser.add_option("--clobber", action="store_true", dest="clobber")
    parser.add_option("--no-clobber", action="store_false", dest="clobber")
    
  • "append" [có liên quan: type, dest, nargs, choices]

    Theo sau tùy chọn này phải là một đối số, được thêm vào danh sách trong dest. Nếu không có giá trị mặc định nào cho dest được cung cấp, một danh sách trống sẽ tự động được tạo khi optparse gặp tùy chọn này lần đầu trên dòng lệnh. Nếu nargs > 1, nhiều đối số sẽ được sử dụng và một bộ có độ dài nargs sẽ được thêm vào dest.

    Giá trị mặc định cho typedest giống như đối với hành động "store".

    Ví dụ:

    Parser.add_option("-t", "--tracks", action="append", type="int")
    

    Nếu -t3 được nhìn thấy trên dòng lệnh, optparse thực hiện tương đương với

    tùy chọn.tracks = []
    tùy chọn.tracks.append(int("3"))
    

    Nếu sau đó một lát, --tracks=4 được nhìn thấy, thì nó sẽ

    tùy chọn.tracks.append(int("4"))
    

    Hành động append gọi phương thức append trên giá trị hiện tại của tùy chọn. Điều này có nghĩa là bất kỳ giá trị mặc định nào được chỉ định đều phải có phương thức append. Điều đó cũng có nghĩa là nếu giá trị mặc định không trống thì các phần tử mặc định sẽ xuất hiện trong giá trị được phân tích cú pháp cho tùy chọn, với mọi giá trị từ dòng lệnh được thêm vào sau các giá trị mặc định đó:

    >>> Parser.add_option("--files", action="append", default=['~/.mypkg/defaults'])
    >>> opts, args = parser.parse_args(['--files', 'overrides.mypkg'])
    >>> opts.files
    ['~/.mypkg/defaults', 'overrides.mypkg']
    
  • "append_const" [bắt buộc: const; có liên quan: dest]

    Giống như "store_const", nhưng giá trị const được thêm vào dest; như với "append", dest mặc định là None và một danh sách trống sẽ tự động được tạo khi gặp tùy chọn này lần đầu tiên.

  • "count" [có liên quan: dest]

    Tăng số nguyên được lưu trữ tại dest. Nếu không có giá trị mặc định nào được cung cấp, dest được đặt thành 0 trước khi tăng lần đầu tiên.

    Ví dụ:

    parser.add_option("-v", action="count", dest="verbosity")
    

    Lần đầu tiên -v được nhìn thấy trên dòng lệnh, optparse thực hiện tương đương với

    tùy chọn.verbosity = 0
    tùy chọn.verbosity += 1
    

    Mỗi lần xuất hiện tiếp theo của -v đều dẫn đến

    tùy chọn.verbosity += 1
    
  • "callback" [bắt buộc: callback; có liên quan: type, nargs, callback_args, callback_kwargs]

    Gọi hàm do callback chỉ định, hàm này được gọi là

    func(tùy chọn, opt_str, giá trị, trình phân tích  pháp, *args, **kwargs)
    

    Xem phần Tùy chọn gọi lại để biết thêm chi tiết.

  • "help"

    In thông báo trợ giúp hoàn chỉnh cho tất cả các tùy chọn trong trình phân tích cú pháp tùy chọn hiện tại. Thông báo trợ giúp được tạo từ chuỗi usage được truyền tới hàm tạo của OptionParser và chuỗi help được truyền cho mọi tùy chọn.

    Nếu không có chuỗi help nào được cung cấp cho một tùy chọn, nó vẫn sẽ được liệt kê trong thông báo trợ giúp. Để bỏ qua hoàn toàn một tùy chọn, hãy sử dụng giá trị đặc biệt optparse.SUPPRESS_HELP.

    optparse tự động thêm tùy chọn help cho tất cả các OptionParsers, vì vậy thông thường bạn không cần phải tạo một tùy chọn.

    Ví dụ:

    từ nhập optparse OptionParser, SUPPRESS_HELP
    
    # usually, một tùy chọn trợ giúp sẽ được thêm tự động, nhưng điều đó có thể
    # be bị chặn bằng cách sử dụng đối số add_help_option
    trình phân tích  pháp = OptionParser(add_help_option=False)
    
    parser.add_option("-h", "--help", action="help")
    parser.add_option("-v", action="store_true", dest="verbose",
                      help="Nói dài vừa phải")
    parser.add_option("--file", dest="filename",
                      help="Nhập tệp để đọc dữ liệu từ")
    parser.add_option("--secret", help=SUPPRESS_HELP)
    

    Nếu optparse thấy -h hoặc --help trên dòng lệnh, nó sẽ in nội dung giống như thông báo trợ giúp sau tới thiết bị xuất chuẩn (giả sử sys.argv[0]"foo.py"):

    Cách sử dụng: foo.py [tùy chọn]
    
    Tùy chọn:
      -h, --help Hiển thị thông báo trợ giúp này và thoát
      -v Hãy dài dòng vừa phải
      --file=FILENAME Tệp đầu vào để đọc dữ liệu từ
    

    Sau khi in thông báo trợ giúp, optparse sẽ kết thúc quá trình của bạn với sys.exit(0).

  • "version"

    In số phiên bản được cung cấp cho OptionParser thành thiết bị xuất chuẩn và thoát. Số phiên bản thực sự được định dạng và in bằng phương pháp print_version() của OptionParser. Nói chung chỉ có liên quan nếu đối số version được cung cấp cho hàm tạo OptionParser. Giống như các tùy chọn help, bạn sẽ hiếm khi tạo các tùy chọn version, vì optparse tự động thêm chúng khi cần.

Các loại tùy chọn tiêu chuẩn

optparse có năm loại tùy chọn tích hợp: "string", "int", "choice", "float""complex". Nếu bạn cần thêm các loại tùy chọn mới, hãy xem phần Mở rộng optparse.

Các đối số cho các tùy chọn chuỗi không được kiểm tra hoặc chuyển đổi theo bất kỳ cách nào: văn bản trên dòng lệnh được lưu trữ ở đích (hoặc được chuyển đến cuộc gọi lại).

Đối số nguyên (loại "int") được phân tích cú pháp như sau:

  • nếu số bắt đầu bằng 0x, nó sẽ được phân tích cú pháp dưới dạng số thập lục phân

  • nếu số bắt đầu bằng 0, nó sẽ được phân tích cú pháp dưới dạng số bát phân

  • nếu số bắt đầu bằng 0b, nó sẽ được phân tích cú pháp dưới dạng số nhị phân

  • mặt khác, số được phân tích cú pháp dưới dạng số thập phân

Việc chuyển đổi được thực hiện bằng cách gọi int() với cơ số thích hợp (2, 8, 10 hoặc 16). Nếu điều này không thành công thì optparse cũng vậy, mặc dù có thông báo lỗi hữu ích hơn.

Các đối số tùy chọn "float""complex" được chuyển đổi trực tiếp bằng float()complex(), với cách xử lý lỗi tương tự.

Tùy chọn "choice" là một loại phụ của tùy chọn "string". Thuộc tính tùy chọn choices (một chuỗi các chuỗi) xác định tập hợp các đối số tùy chọn được phép. optparse.check_choice() so sánh các đối số tùy chọn do người dùng cung cấp với danh sách chính này và tăng OptionValueError nếu đưa ra một chuỗi không hợp lệ.

Phân tích đối số

Toàn bộ mục đích của việc tạo và điền OptionParser là gọi phương thức parse_args() của nó.

OptionParser.parse_args(args=None, values=None)

Phân tích các tùy chọn dòng lệnh có trong args.

Các thông số đầu vào là

args

danh sách các đối số cần xử lý (mặc định: sys.argv[1:])

values

một đối tượng Values để lưu trữ các đối số tùy chọn trong (mặc định: một phiên bản mới của Values) -- nếu bạn cung cấp một đối tượng hiện có, các giá trị mặc định của tùy chọn sẽ không được khởi tạo trên nó

và giá trị trả về là một cặp (options, args) trong đó

options

cùng một đối tượng được truyền vào dưới dạng values hoặc phiên bản optparse.Values được tạo bởi optparse

args

các đối số vị trí còn sót lại sau khi tất cả các tùy chọn đã được xử lý

Cách sử dụng phổ biến nhất là không cung cấp đối số từ khóa. Nếu bạn cung cấp values, nó sẽ được sửa đổi bằng các lệnh gọi setattr() lặp đi lặp lại (khoảng một lệnh cho mỗi đối số tùy chọn được lưu trữ đến đích tùy chọn) và được trả về bởi parse_args().

Nếu parse_args() gặp bất kỳ lỗi nào trong danh sách đối số, nó sẽ gọi phương thức error() của OptionParser kèm theo thông báo lỗi thích hợp cho người dùng cuối. Điều này cuối cùng sẽ chấm dứt quá trình của bạn với trạng thái thoát là 2 (trạng thái thoát Unix truyền thống đối với các lỗi dòng lệnh).

Truy vấn và thao tác trình phân tích cú pháp tùy chọn của bạn

Hành vi mặc định của trình phân tích cú pháp tùy chọn có thể được tùy chỉnh một chút và bạn cũng có thể xem xét trình phân tích cú pháp tùy chọn của mình và xem những gì ở đó. OptionParser cung cấp một số phương pháp để giúp bạn:

OptionParser.disable_interspersed_args()

Đặt phân tích cú pháp để dừng ở tùy chọn không đầu tiên. Ví dụ: nếu -a-b đều là các tùy chọn đơn giản không có đối số, thì optparse thường chấp nhận cú pháp này:

prog -a arg1 -b arg2

và coi nó tương đương với

prog -a -b arg1 arg2

Để tắt tính năng này, hãy gọi disable_interspersed_args(). Điều này khôi phục cú pháp Unix truyền thống, trong đó việc phân tích cú pháp tùy chọn dừng lại với đối số không phải tùy chọn đầu tiên.

Sử dụng tùy chọn này nếu bạn có bộ xử lý lệnh chạy một lệnh khác có các tùy chọn riêng và bạn muốn đảm bảo các tùy chọn này không bị nhầm lẫn. Ví dụ: mỗi lệnh có thể có một bộ tùy chọn khác nhau.

OptionParser.enable_interspersed_args()

Đặt phân tích cú pháp để không dừng ở tùy chọn không đầu tiên, cho phép chuyển đổi xen kẽ với các đối số lệnh. Đây là hành vi mặc định.

OptionParser.get_option(opt_str)

Trả về phiên bản Tùy chọn có chuỗi tùy chọn opt_str hoặc None nếu không có tùy chọn nào có chuỗi tùy chọn đó.

OptionParser.has_option(opt_str)

Trả về True nếu OptionParser có tùy chọn với chuỗi tùy chọn opt_str (ví dụ: -q hoặc --verbose).

OptionParser.remove_option(opt_str)

Nếu OptionParser có tùy chọn tương ứng với opt_str thì tùy chọn đó sẽ bị loại bỏ. Nếu tùy chọn đó cung cấp bất kỳ chuỗi tùy chọn nào khác thì tất cả các chuỗi tùy chọn đó sẽ không hợp lệ. Nếu opt_str không xuất hiện trong bất kỳ tùy chọn nào thuộc OptionParser này, hãy tăng ValueError.

Xung đột giữa các lựa chọn

Nếu không cẩn thận, bạn rất dễ xác định các tùy chọn có chuỗi tùy chọn xung đột nhau:

Parser.add_option("-n", "--dry-run", ...)
...
Parser.add_option("-n", "--noisy", ...)

(Điều này đặc biệt đúng nếu bạn đã xác định lớp con OptionParser của riêng mình bằng một số tùy chọn tiêu chuẩn.)

Mỗi khi bạn thêm một tùy chọn, optparse sẽ kiểm tra xung đột với các tùy chọn hiện có. Nếu tìm thấy bất kỳ điều gì, nó sẽ gọi cơ chế xử lý xung đột hiện tại. Bạn có thể đặt cơ chế xử lý xung đột trong hàm tạo

trình phân tích  pháp = OptionParser(..., xung đột_handler=handler)

hoặc với một cuộc gọi riêng:

trình phân tích  pháp.set_conflict_handler(trình xử )

Các trình xử lý xung đột có sẵn là:

"error" (mặc định)

giả sử xung đột tùy chọn là lỗi lập trình và tăng OptionConflictError

"resolve"

giải quyết xung đột tùy chọn một cách thông minh (xem bên dưới)

Ví dụ: hãy xác định một OptionParser giải quyết xung đột một cách thông minh và thêm các tùy chọn xung đột vào nó:

trình phân tích  pháp = OptionParser(conflict_handler="resolve")
parser.add_option("-n", "--dry-run", ..., help="không gây hại")
Parser.add_option("-n", "--noisy", ..., help="ồn ào")

Tại thời điểm này, optparse phát hiện ra rằng tùy chọn được thêm trước đó đã sử dụng chuỗi tùy chọn -n. Vì conflict_handler"resolve" nên nó sẽ giải quyết tình huống này bằng cách xóa -n khỏi danh sách chuỗi tùy chọn của tùy chọn trước đó. Bây giờ --dry-run là cách duy nhất để người dùng kích hoạt tùy chọn đó. Nếu người dùng yêu cầu trợ giúp, thông báo trợ giúp sẽ phản ánh rằng:

Tùy chọn:
  --chạy khô không gây hại 
  ...
  -n, --ồn ào ồn ào

Có thể cắt bớt các chuỗi tùy chọn cho một tùy chọn đã thêm trước đó cho đến khi không còn chuỗi tùy chọn nào và người dùng không có cách nào gọi tùy chọn đó từ dòng lệnh. Trong trường hợp đó, optparse loại bỏ hoàn toàn tùy chọn đó nên nó không hiển thị trong văn bản trợ giúp hoặc bất kỳ nơi nào khác. Tiếp tục với OptionParser hiện có của chúng tôi:

Parser.add_option("--dry-run", ..., help="tùy chọn chạy thử mới")

Tại thời điểm này, tùy chọn -n/--dry-run ban đầu không còn truy cập được nữa nên optparse sẽ xóa nó, để lại văn bản trợ giúp này:

Tùy chọn:
  ...
  -n, --ồn ào ồn ào
  --dry-run tùy chọn chạy khô mới

Dọn dẹp

Các phiên bản OptionParser có một số tham chiếu tuần hoàn. Đây không phải là vấn đề đối với trình thu gom rác của Python, nhưng bạn có thể muốn phá vỡ các tham chiếu tuần hoàn một cách rõ ràng bằng cách gọi destroy() trên OptionParser sau khi bạn đã hoàn tất. Điều này đặc biệt hữu ích trong các ứng dụng chạy dài, nơi có thể truy cập được các biểu đồ đối tượng lớn từ OptionParser của bạn.

Các phương pháp khác

OptionParser hỗ trợ một số phương thức công khai khác:

OptionParser.set_usage(usage)

Đặt chuỗi sử dụng theo các quy tắc được mô tả ở trên cho đối số từ khóa hàm tạo usage. Truyền None sẽ đặt chuỗi sử dụng mặc định; sử dụng optparse.SUPPRESS_USAGE để chặn thông báo sử dụng.

OptionParser.print_usage(file=None)

In thông báo sử dụng cho chương trình hiện tại (self.usage) thành file (thiết bị xuất chuẩn mặc định). Bất kỳ sự xuất hiện nào của chuỗi %prog trong self.usage đều được thay thế bằng tên của chương trình hiện tại. Không có gì nếu self.usage trống hoặc không được xác định.

OptionParser.get_usage()

Tương tự như print_usage() nhưng trả về chuỗi sử dụng thay vì in ra.

OptionParser.set_defaults(dest=value, ...)

Đặt giá trị mặc định cho một số đích tùy chọn cùng một lúc. Sử dụng set_defaults() là cách ưu tiên để đặt giá trị mặc định cho các tùy chọn vì nhiều tùy chọn có thể chia sẻ cùng một đích. Ví dụ: nếu một số tùy chọn "chế độ" đều đặt cùng một đích đến thì bất kỳ tùy chọn nào trong số chúng đều có thể đặt mặc định và tùy chọn cuối cùng sẽ thắng:

parser.add_option("--advanced", action="store_const",
                  dest="mode", const="nâng cao",
                  mặc định="người mới") # overridden bên dưới
parser.add_option("--novice", action="store_const",
                  dest="mode", const="người mới",
                  cài đặt mặc định="nâng cao") # overrides ở trên

Để tránh sự nhầm lẫn này, hãy sử dụng set_defaults():

trình phân tích  pháp.set_defaults(mode="advanced")
parser.add_option("--advanced", action="store_const",
                  dest="mode", const="nâng cao")
parser.add_option("--novice", action="store_const",
                  dest="mode", const="người mới")

Tùy chọn gọi lại

Khi các loại và hành động tích hợp sẵn của optparse không đủ đáp ứng nhu cầu của bạn, bạn có hai lựa chọn: mở rộng optparse hoặc xác định tùy chọn gọi lại. Việc mở rộng optparse mang tính tổng quát hơn nhưng lại quá mức cần thiết đối với nhiều trường hợp đơn giản. Thông thường, một cuộc gọi lại đơn giản là tất cả những gì bạn cần.

Có hai bước để xác định tùy chọn gọi lại:

  • tự xác định tùy chọn bằng hành động "callback"

  • viết cuộc gọi lại; đây là một hàm (hoặc phương thức) có ít nhất bốn đối số, như được mô tả bên dưới

Xác định tùy chọn gọi lại

Như mọi khi, cách dễ nhất để xác định tùy chọn gọi lại là sử dụng phương thức OptionParser.add_option(). Ngoài action, thuộc tính tùy chọn duy nhất bạn phải chỉ định là callback, hàm để gọi

parser.add_option("-c", action="callback", callback=my_callback)

callback là một hàm (hoặc đối tượng có thể gọi khác), vì vậy bạn phải xác định my_callback() khi tạo tùy chọn gọi lại này. Trong trường hợp đơn giản này, optparse thậm chí không biết liệu -c có nhận bất kỳ đối số nào hay không, điều này thường có nghĩa là tùy chọn này không có đối số---chỉ sự hiện diện của -c trên dòng lệnh là tất cả những gì nó cần biết. Tuy nhiên, trong một số trường hợp, bạn có thể muốn lệnh gọi lại của mình sử dụng số lượng đối số dòng lệnh tùy ý. Đây là lúc việc viết lệnh gọi lại trở nên khó khăn; nó sẽ được đề cập sau trong phần này.

optparse luôn chuyển bốn đối số cụ thể cho lệnh gọi lại của bạn và nó sẽ chỉ chuyển các đối số bổ sung nếu bạn chỉ định chúng thông qua callback_argscallback_kwargs. Do đó, chữ ký hàm gọi lại tối thiểu là:

def my_callback(tùy chọn, opt, value, trình phân tích  pháp):

Bốn đối số cho lệnh gọi lại được mô tả bên dưới.

Có một số thuộc tính tùy chọn khác mà bạn có thể cung cấp khi xác định tùy chọn gọi lại:

type

có ý nghĩa thông thường: như với các hành động "store" hoặc "append", nó hướng dẫn optparse sử dụng một đối số và chuyển đổi nó thành type. Tuy nhiên, thay vì lưu trữ (các) giá trị đã chuyển đổi ở bất kỳ đâu, optparse chuyển nó tới hàm gọi lại của bạn.

nargs

cũng có ý nghĩa thông thường: nếu nó được cung cấp và > 1, optparse sẽ sử dụng các đối số nargs, mỗi đối số đó phải có thể chuyển đổi thành type. Sau đó, nó chuyển một bộ giá trị đã chuyển đổi sang lệnh gọi lại của bạn.

callback_args

một bộ đối số vị trí bổ sung để chuyển đến lệnh gọi lại

callback_kwargs

một từ điển các đối số từ khóa bổ sung để chuyển đến cuộc gọi lại

Cách gọi lại

Tất cả các cuộc gọi lại được gọi như sau:

func(tùy chọn, opt_str, giá trị, trình phân tích  pháp, *args, **kwargs)

ở đâu

option

là phiên bản Tùy chọn đang gọi lại cuộc gọi lại

opt_str

là chuỗi tùy chọn nhìn thấy trên dòng lệnh đang kích hoạt lệnh gọi lại. (Nếu sử dụng tùy chọn dài viết tắt, opt_str sẽ là chuỗi tùy chọn chuẩn, đầy đủ---ví dụ: nếu người dùng đặt --foo trên dòng lệnh làm tên viết tắt cho --foobar thì opt_str sẽ là "--foobar".)

value

là đối số cho tùy chọn này được thấy trên dòng lệnh. optparse sẽ chỉ mong đợi một đối số nếu type được đặt; loại value sẽ là loại được ngụ ý bởi loại tùy chọn. Nếu type cho tùy chọn này là None (không có đối số dự kiến), thì value sẽ là None. Nếu nargs > 1, value sẽ là một bộ giá trị thuộc loại thích hợp.

parser

là phiên bản OptionParser điều khiển toàn bộ nội dung, chủ yếu hữu ích vì bạn có thể truy cập một số dữ liệu thú vị khác thông qua các thuộc tính phiên bản của nó:

parser.largs

danh sách hiện tại của các đối số còn sót lại, tức là. các đối số đã được sử dụng nhưng không phải là đối số tùy chọn cũng như đối số tùy chọn. Vui lòng sửa đổi parser.largs, ví dụ: bằng cách thêm nhiều đối số vào nó. (Danh sách này sẽ trở thành args, giá trị trả về thứ hai của parse_args().)

parser.rargs

danh sách hiện tại của các đối số còn lại, tức là. với opt_strvalue (nếu có) đã bị xóa và chỉ các đối số theo sau chúng vẫn còn đó. Vui lòng sửa đổi parser.rargs, ví dụ: bằng cách tiêu tốn nhiều đối số hơn.

parser.values

đối tượng nơi các giá trị tùy chọn được lưu trữ theo mặc định (một phiên bản của optparse.OptionValues). Điều này cho phép lệnh gọi lại sử dụng cơ chế tương tự như phần còn lại của optparse để lưu trữ các giá trị tùy chọn; bạn không cần phải loay hoay với toàn cầu hoặc đóng cửa. Bạn cũng có thể truy cập hoặc sửa đổi (các) giá trị của bất kỳ tùy chọn nào đã gặp trên dòng lệnh.

args

là một bộ đối số vị trí tùy ý được cung cấp thông qua thuộc tính tùy chọn callback_args.

kwargs

là một từ điển gồm các đối số từ khóa tùy ý được cung cấp qua callback_kwargs.

Phát sinh lỗi trong cuộc gọi lại

Hàm gọi lại sẽ tăng OptionValueError nếu có bất kỳ vấn đề nào với tùy chọn hoặc (các) đối số của nó. optparse phát hiện ra điều này và kết thúc chương trình, in thông báo lỗi mà bạn cung cấp cho stderr. Thông điệp của bạn phải rõ ràng, ngắn gọn, chính xác và đề cập đến phương án có lỗi. Nếu không, người dùng sẽ khó nhận ra mình đã làm gì sai.

Ví dụ gọi lại 1: gọi lại tầm thường

Dưới đây là ví dụ về tùy chọn gọi lại không có đối số và chỉ ghi lại rằng tùy chọn đã được nhìn thấy:

def record_foo_seen(tùy chọn, opt_str, giá trị, trình phân tích  pháp):
    trình phân tích  pháp.values.saw_foo = Đúng

parser.add_option("--foo", action="callback", callback=record_foo_seen)

Tất nhiên, bạn có thể làm điều đó với hành động "store_true".

Ví dụ gọi lại 2: kiểm tra thứ tự tùy chọn

Đây là một ví dụ thú vị hơn một chút: ghi lại thực tế là -a được nhìn thấy, nhưng sẽ bùng nổ nếu nó xuất hiện sau -b trong dòng lệnh.

def check_order(tùy chọn, opt_str, giá trị, trình phân tích  pháp):
    nếu trình phân tích  pháp.values.b:
        raise OptionValueError("không thể sử dụng -a sau -b")
    trình phân tích  pháp.values.a = 1
...
parser.add_option("-a", action="callback", callback=check_order)
parser.add_option("-b", action="store_true", dest="b")

Ví dụ gọi lại 3: kiểm tra thứ tự tùy chọn (tổng quát)

Nếu bạn muốn sử dụng lại lệnh gọi lại này cho một số tùy chọn tương tự (đặt cờ, nhưng sẽ nổ tung nếu -b đã được nhìn thấy), nó cần một chút công việc: thông báo lỗi và cờ mà nó đặt phải được khái quát hóa.

def check_order(tùy chọn, opt_str, giá trị, trình phân tích  pháp):
    nếu trình phân tích  pháp.values.b:
        raise OptionValueError("không thể sử dụng %s sau -b" % opt_str)
    setattr(parser.values, option.dest, 1)
...
parser.add_option("-a", action="callback", callback=check_order, dest='a')
parser.add_option("-b", action="store_true", dest="b")
parser.add_option("-c", action="callback", callback=check_order, dest='c')

Ví dụ gọi lại 4: kiểm tra điều kiện tùy ý

Tất nhiên, bạn có thể đặt bất kỳ điều kiện nào vào đó---bạn không bị giới hạn trong việc kiểm tra giá trị của các tùy chọn đã được xác định. Ví dụ: nếu bạn có các tùy chọn không nên gọi khi trăng tròn, tất cả những gì bạn phải làm là thế này:

def check_moon (tùy chọn, opt_str, giá trị, trình phân tích  pháp):
    nếu is_moon_full():
        raise OptionValueError("tùy chọn %s không hợp lệ khi trăng tròn"
                               % opt_str)
    setattr(parser.values, option.dest, 1)
...
trình phân tích  pháp.add_option("--foo",
                  action="callback", callback=check_moon, dest="foo")

(Định nghĩa về is_moon_full() được để lại như một bài tập cho người đọc.)

Ví dụ gọi lại 5: đối số cố định

Mọi thứ trở nên thú vị hơn một chút khi bạn xác định các tùy chọn gọi lại có số lượng đối số cố định. Việc chỉ định rằng tùy chọn gọi lại nhận các đối số cũng tương tự như việc xác định tùy chọn "store" hoặc "append": nếu bạn xác định type thì tùy chọn này sẽ nhận một đối số phải có thể chuyển đổi sang loại đó; nếu bạn xác định thêm nargs thì tùy chọn này sẽ lấy các đối số nargs.

Đây là một ví dụ chỉ mô phỏng hành động "store" tiêu chuẩn:

def store_value (tùy chọn, opt_str, giá trị, trình phân tích  pháp):
    setattr(parser.values, option.dest, value)
...
trình phân tích  pháp.add_option("--foo",
                  hành động="gọi lại", gọi lại=store_value,
                  type="int", nargs=3, dest="foo")

Lưu ý rằng optparse đảm nhiệm việc sử dụng 3 đối số và chuyển đổi chúng thành số nguyên cho bạn; tất cả những gì bạn phải làm là lưu trữ chúng. (Hoặc bất cứ điều gì; rõ ràng là bạn không cần gọi lại cho ví dụ này.)

Ví dụ gọi lại 6: đối số biến

Mọi thứ trở nên rắc rối khi bạn muốn có một tùy chọn để nhận số lượng đối số thay đổi. Trong trường hợp này, bạn phải viết một lệnh gọi lại vì optparse không cung cấp bất kỳ khả năng tích hợp nào cho nó. Và bạn phải giải quyết một số vấn đề phức tạp nhất định của việc phân tích cú pháp dòng lệnh Unix thông thường mà optparse thường xử lý cho bạn. Cụ thể, các lệnh gọi lại phải triển khai các quy tắc thông thường cho các đối số --- trần:

  • -- hoặc - có thể là đối số tùy chọn

  • -- trần (nếu không phải là đối số cho một số tùy chọn): tạm dừng xử lý dòng lệnh và loại bỏ --

  • - trần (nếu không phải là đối số cho một số tùy chọn): tạm dừng xử lý dòng lệnh nhưng giữ lại - (thêm nó vào parser.largs)

Nếu bạn muốn một tùy chọn có số lượng đối số thay đổi thì có một số vấn đề tế nhị, phức tạp cần phải lo lắng. Cách triển khai chính xác mà bạn chọn sẽ dựa trên những đánh đổi mà bạn sẵn sàng thực hiện cho ứng dụng của mình (đó là lý do tại sao optparse không hỗ trợ trực tiếp loại điều này).

Tuy nhiên, đây là một thử thách trong cuộc gọi lại cho một tùy chọn có các đối số thay đổi

def vararg_callback(tùy chọn, opt_str, giá trị, trình phân tích  pháp):
    khẳng định giá trị  Không 
    giá trị = []

    def  thể nổi (str):
        thử:
            phao(str)
            trả về Đúng
        ngoại trừ ValueError:
            trả về Sai

    cho arg trong trình phân tích  pháp.rargs:
        # stop trên --foo tùy chọn thích
        nếu arg[:2] == "--"  len(arg) > 2:
            phá vỡ
        # stop trên -a, nhưng không phải trên -3 hoặc -3.0
        nếu arg[:1] == "-"  len(arg) > 1  không thể nổi (arg):
            phá vỡ
        value.append(arg)

    del parser.rargs[:len(value)]
    setattr(parser.values, option.dest, value)

...
parser.add_option("-c", "--callback", dest="vararg_attr",
                  hành động="gọi lại", gọi lại=vararg_callback)

Mở rộng optparse

Vì hai yếu tố kiểm soát chính trong cách optparse diễn giải các tùy chọn dòng lệnh là hành động và loại của từng tùy chọn, nên hướng mở rộng có khả năng nhất là thêm các hành động mới và loại mới.

Thêm loại mới

Để thêm các loại mới, bạn cần xác định lớp con của lớp Option của optparse. Lớp này có một số thuộc tính xác định các loại của optparse: TYPESTYPE_CHECKER.

Option.TYPES

Một bộ tên loại; trong lớp con của bạn, chỉ cần xác định một bộ TYPES mới được xây dựng trên bộ tiêu chuẩn.

Option.TYPE_CHECKER

Một từ điển ánh xạ tên loại tới các chức năng kiểm tra loại. Hàm kiểm tra loại có chữ ký sau

def check_mytype(tùy chọn, opt, value)

trong đó option là một phiên bản Option, opt là một chuỗi tùy chọn (ví dụ: -f) và value là chuỗi từ dòng lệnh phải được kiểm tra và chuyển đổi thành loại bạn muốn. check_mytype() sẽ trả về một đối tượng thuộc loại giả định mytype. Giá trị được hàm kiểm tra loại trả về sẽ xuất hiện trong phiên bản OptionValues ​​được OptionParser.parse_args() trả về hoặc được chuyển đến lệnh gọi lại dưới dạng tham số value.

Chức năng kiểm tra loại của bạn sẽ tăng OptionValueError nếu gặp bất kỳ vấn đề nào. OptionValueError lấy một đối số chuỗi đơn, được truyền nguyên trạng cho phương thức error() của OptionParser, lần lượt thêm tên chương trình và chuỗi "error:" và in mọi thứ vào stderr trước khi kết thúc quá trình.

Đây là một ví dụ ngớ ngẩn minh họa việc thêm loại tùy chọn "complex" để phân tích các số phức kiểu Python trên dòng lệnh. (Điều này thậm chí còn ngớ ngẩn hơn trước đây vì optparse 1.3 đã thêm hỗ trợ tích hợp cho các số phức, nhưng đừng bận tâm.)

Đầu tiên, nhập khẩu cần thiết:

từ bản sao nhập bản sao
từ tùy chọn nhập optparse, OptionValueError

Trước tiên, bạn cần xác định trình kiểm tra loại của mình vì nó được đề cập đến sau (trong thuộc tính lớp TYPE_CHECKER của lớp con Tùy chọn của bạn):

def check_complex(tùy chọn, opt, value):
    thử:
        trả về phức tạp (giá trị)
    ngoại trừ ValueError:
        nâng cao OptionValueError(
            "tùy chọn %s: giá trị phức hợp không hợp lệ: %r" % (tùy chọn, giá trị))

Cuối cùng, lớp con Tùy chọn:

lớp MyOption (Tùy chọn):
    TYPES = Option.TYPES + ("phức tạp",)
    TYPE_CHECKER = sao chép(Option.TYPE_CHECKER)
    TYPE_CHECKER["complex"] = check_complex

(Nếu chúng tôi không tạo copy() của Option.TYPE_CHECKER, thì cuối cùng chúng tôi sẽ sửa đổi thuộc tính TYPE_CHECKER của lớp Tùy chọn của optparse. Đây là Python, không có gì ngăn cản bạn làm điều đó ngoại trừ cách cư xử tốt và lẽ thường.)

Thế thôi! Bây giờ bạn có thể viết một tập lệnh sử dụng loại tùy chọn mới giống như bất kỳ tập lệnh dựa trên optparse- nào khác, ngoại trừ bạn phải hướng dẫn OptionParser sử dụng MyOption thay vì Option:

trình phân tích  pháp = OptionParser(option_class=MyOption)
Parser.add_option("-c", type="complex")

Ngoài ra, bạn có thể xây dựng danh sách tùy chọn của riêng mình và chuyển nó tới OptionParser; nếu bạn không sử dụng add_option() theo cách trên, bạn không cần phải cho OptionParser biết nên sử dụng lớp tùy chọn nào:

option_list = [MyOption("-c", action="store", type="complex", dest="c")]
trình phân tích  pháp = OptionParser(option_list=option_list)

Thêm hành động mới

Việc thêm hành động mới phức tạp hơn một chút vì bạn phải hiểu rằng optparse có một số cách phân loại cho hành động:

hành động "lưu trữ"

các hành động dẫn đến việc optparse lưu trữ một giá trị vào một thuộc tính của phiên bản OptionValues hiện tại; các tùy chọn này yêu cầu cung cấp thuộc tính dest cho hàm tạo Tùy chọn.

hành động "gõ"

các hành động lấy một giá trị từ dòng lệnh và mong đợi nó thuộc một loại nhất định; hay đúng hơn là một chuỗi có thể được chuyển đổi thành một loại nhất định. Các tùy chọn này yêu cầu thuộc tính type cho hàm tạo Tùy chọn.

Đây là các tập hợp chồng chéo: một số hành động "lưu trữ" mặc định là "store", "store_const", "append""count", trong khi các hành động "đã nhập" mặc định là "store", "append""callback".

Khi thêm một hành động, bạn cần phân loại nó bằng cách liệt kê nó vào ít nhất một trong các thuộc tính lớp sau của Tùy chọn (tất cả đều là danh sách các chuỗi):

Option.ACTIONS

Tất cả các hành động phải được liệt kê trong ACTIONS.

Option.STORE_ACTIONS

hành động "lưu trữ" cũng được liệt kê ở đây.

Option.TYPED_ACTIONS

hành động "đã gõ" cũng được liệt kê ở đây.

Option.ALWAYS_TYPED_ACTIONS

Các hành động luôn có một loại (tức là các tùy chọn của chúng luôn nhận một giá trị) cũng được liệt kê thêm ở đây. Tác dụng duy nhất của việc này là optparse chỉ định loại mặc định, "string", cho các tùy chọn không có loại rõ ràng có hành động được liệt kê trong ALWAYS_TYPED_ACTIONS.

Để thực sự triển khai hành động mới của mình, bạn phải ghi đè phương thức take_action() của Tùy chọn và thêm trường hợp nhận dạng hành động của bạn.

Ví dụ: hãy thêm một hành động "extend". Điều này tương tự như hành động "append" tiêu chuẩn, nhưng thay vì lấy một giá trị từ dòng lệnh và thêm nó vào danh sách hiện có, "extend" sẽ lấy nhiều giá trị trong một chuỗi được phân cách bằng dấu phẩy và mở rộng danh sách hiện có với chúng. Tức là, nếu --names là một tùy chọn "extend" thuộc loại "string", thì dòng lệnh

--names=foo,bar --names blah --names ding,dong

sẽ dẫn đến một danh sách

["foo", "bar", "blah", "ding", "dong"]

Một lần nữa chúng ta định nghĩa một lớp con của Option:

lớp MyOption(Tùy chọn):

    ACTIONS = Option.ACTIONS + ("mở rộng",)
    STORE_ACTIONS = Option.STORE_ACTIONS + ("mở rộng",)
    TYPED_ACTIONS = Option.TYPED_ACTIONS + ("mở rộng",)
    ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("mở rộng",)

    def take_action(self, action, dest, opt, value, value, trình phân tích  pháp):
        nếu hành động == "mở rộng":
            lvalue = value.split(",")
            value.ensure_value(dest, []).extend(lvalue)
        khác:
            Tùy chọn.take_action(
                tự, hành động, đích, opt, giá trị, giá trị, trình phân tích  pháp)

Đặc điểm lưu ý:

  • "extend" đều mong đợi một giá trị trên dòng lệnh và lưu trữ giá trị đó ở đâu đó, do đó, nó có trong cả STORE_ACTIONSTYPED_ACTIONS.

  • để đảm bảo rằng optparse chỉ định loại hành động "string" mặc định cho "extend", chúng tôi cũng đặt hành động "extend" trong ALWAYS_TYPED_ACTIONS.

  • MyOption.take_action() chỉ thực hiện một hành động mới này và chuyển quyền kiểm soát trở lại Option.take_action() cho các hành động optparse tiêu chuẩn.

  • values là một phiên bản của lớp optparse_parser.Values, lớp này cung cấp phương thức ensure_value() rất hữu ích. ensure_value() thực chất là getattr() có van an toàn; nó được gọi là

    value.ensure_value(attr, value)
    

    Nếu thuộc tính attr của values không tồn tại hoặc là None, thì trước tiên, Ensure_value() sẽ đặt thuộc tính đó thành value, sau đó trả về value. Điều này rất thuận tiện cho các hành động như "extend", "append""count", tất cả đều tích lũy dữ liệu trong một biến và dự kiến ​​biến đó thuộc một loại nhất định (danh sách cho hai biến đầu tiên, một số nguyên cho biến sau). Việc sử dụng ensure_value() có nghĩa là các tập lệnh sử dụng hành động của bạn không phải lo lắng về việc đặt giá trị mặc định cho đích tùy chọn được đề cập; họ chỉ có thể để mặc định vì Noneensure_value() sẽ đảm nhiệm việc thực hiện đúng khi cần.

Ngoại lệ

exception optparse.OptionError

Xảy ra nếu một phiên bản Option được tạo với các đối số không hợp lệ hoặc không nhất quán.

exception optparse.OptionConflictError

Tăng lên nếu các tùy chọn xung đột được thêm vào OptionParser.

exception optparse.OptionValueError

Tăng lên nếu gặp giá trị tùy chọn không hợp lệ trên dòng lệnh.

exception optparse.BadOptionError

Tăng lên nếu một tùy chọn không hợp lệ được truyền vào dòng lệnh.

exception optparse.AmbiguousOptionError

Xảy ra nếu một tùy chọn không rõ ràng được truyền trên dòng lệnh.