+5

PyMOTM: Argparse

Chắc hẳn trong chúng ta, ai cũng đã từng ít nhất một lần làm việc trên console (terminal). Và việc sử dụng một ứng dụng nào đó đều có các tùy chọn rất là phong phú. Đúng không ạ? Ví dụ như lệnh cp (copy) trên Ubuntu. Khi bạn truyền tham số --help hoặc man cp sẽ nhận được hướng dẫn đầy đủ với rất nhiều tùy chọn khác nhau. Có bao giờ bạn tự thắc mắc rằng nó nhận và parse các tham số (tùy chọn) đấy như thế nào không? Chúng ta cùng đi tìm hiểu về nó ở ngôn ngữ Python nhé 😄!

Argparse - Command line option and argument parsing

Mục đích: Parse các tham số và tùy chọn trên command line

Module Argparse được thêm vào Python từ phiên bản 2.7 nhằm thay thế cho module Optparse. Argpase có nhiều tính năng mà bạn khó có thể tìm được ở module Optparse. Việc thay thế này không có nghĩa là bạn sẽ không sử dụng được module Optparse vì Optparse vẫn được Python hỗ trợ, nhưng sẽ không nhận được các tính năng mới trong tương lai.

Cài đặt

Nếu bạn đã cài Python 2.7 trở lên thì không cần phải cài đặt gì cả. Vì nó được thêm vào core của Python nhằm cho việc thay thế Optparse. Còn nếu bạn dùng Python 2.6 thì bạn chỉ có cách là nâng cấp phiên bản của Python lên 2.7 😄! OK, chúng ta đi vào chi tiết của module này nhé.

Ví dụ

Để sử dụng Argparse. Bạn chỉ cần import nó vào trong code và khởi tạo class ArgumentParser là có thể sử dụng được. Chúng ta cùng xem ví dụ nhỏ dưới đây nhé:

#!/usr/bin/env python

# pymotm.py

import argparse

parser = argparse.ArgumentParser(description="PyMOTM: Python module of the month")
args = parser.parse_args();

# Đoạn này để đảm bảo rằng khi chương trình được chạy mà không truyền tham số gì thì nó sẽ hiển thị phần trợ giúp chi tiết. Nếu bạn copy đoạn code này để thử. Vui lòng xóa đoạn comment này trước khi chạy chương trình.
if __name__ == "__main__":
    parser.print_help()

Bây giờ chúng ta chạy thử python pymotn.py hoặc python pymotm.py -h xem thế nào nhé 😄! Vậy là bạn đã có cái nhìn đầu tiên về Argparse rồi. Chúng ta sẽ tìm hiểu tiếp xem constructor của class ArgumentParser có những tham số nào nhé 😄!

  • prog: Tên của chương trình. Nếu không có, mặc định nó sẽ lấy từ sys.argv[0] - tên file
  • usage: Đoạn văn bản để mô tả cách sử dụng hay giới thiệu chương trình.
  • description: Text sẽ được hiển thị trước nội dung trợ giúp
  • epilog: Text sẽ được hiển thị sau khi kết thúc hết phần nội dung trợ giúp
  • parents: Mảng object của ArgumentParser khác.
  • formatter_class: Tên class mà bạn muốn sử dụng để hiển thị nội dung trợ giúp. Hiện tại Argparse hỗ trợ những class sau: RawDescriptionHelpFormatter, RawTextHelpFormatter, ArgumentDefaultsHelpFormatterMetavarTypeHelpFormatter
  • prefix_chars: Tập hợp các ký tự mà bạn muốn sử dụng trước những tham số tùy chọn. Mặc định là dấu -
  • fromfile_prefix_chars: Tập hợp các ký tự mà bạn muốn sử dụng trước các tham số liên quan đến đường dẫn của file. Mặc định của tham số này là None
  • argument_default: Giá trị mặc định cho các tham số. Mặc định là None
  • conflict_handler: Giúp bạn handler trong trường hợp bạn thêm một tham số nào đó nhiều hơn 1 lần. Tham số này nhận giá trị là resolve
  • add_help: Tự thêm tham số -h/--help vào chương trình của bạn. Mặc định là True
  • allow_abbrev: Cho phép viết tắt các tùy chọn nào đó quá dài (nếu có thể và từ viết tắt phải rõ ràng). Ví dụ bạn có option là --no-download thì người dùng có thể sử dụng --n hoặc --no. Giá trị mặc định của tham số này là True

OK, xong phần giới thiệu về constructor của class ArgumentParser. Bây giờ chúng ta tìm hiểu một số method của class này nhé.

Method add_argument()

ArgumentParser.add_argument(name or flags...[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest])

Định nghĩa một tham số nào đó mà chương trình của bạn cần parse. Method này có những tham số sau:

  • name or flag: Tên hoặc một danh sách các tên của tùy chọn đó. Ví dụ: foo, -f hoặc --foo

  • action: Tên của action sẽ được thực hiện khi tham số đó được nhập. Chúng ta có những action cơ bản sau:

    • store: Lưu lại giá trị người dùng đã nhập vào name or flag. Action này là action mặc định

    • store_const: Lưu giá trị nhận được vào tham số const

    • store_truestore_false: Một trường hợp đặc biệt của store_const giúp bạn lưu giá trị boolean vào name or flag. Ví dụ:

      #!/usr/bin/env python
      
      # set-false.py
      
      import argparse
      
      parser = argparse.ArgumentParser(description="Example for store true & false")
      parser.add_argument("--set-false", "--s", "--sf", help="Set var_name to false", dest="var_name", action="store_false")
      parser.set_defaults(var_name=True)
      
      args = parser.parse_args()
      
      print "var_name is %s" % args.var_name
      
      

      Bạn thử chạy chương trình với những tùy chọn sau và xem kết quả nhé:

      • python set-false.py
      • python set-false.py -h
      • python set-false.py --set-false
      • python set-false.py --s
      • python set-false.py --sf
    • append: Giá trị sẽ được lưu ở 1 list. Khi sử dụng action này, giá trị mới sẽ đc thêm vào cuối list đó.

    • append_const: Giống với append nhưng áp dụng cho constant.

    • count: Đếm số lần xuất hiện của tham số đó.

    • help: Action này giúp bạn tạo một tham số khác cũng hiển thị nội dung trợ giúp như khi dùng -h/--help

    • version: Giúp bạn hiển thị phiên bản của chương trình. Action này cần đi cùng với tham số version. Ví dụ:

      parser.add_argument("-v", "--version", action="version", version="%(prog)s 1.0")
      
  • nargs: Số lượng tham số mà bạn cần. Giá trị mặc định là 1.

  • const: Giá trị không đổi cho một vài action hay nargs

  • default: Giá trị mặc định cho tùy chọn nếu như tùy chọn đó không được chọn

  • type: Kiểu của giá trị sẽ được convert. Ví dụ: float hoặc int

  • choices: Mảng các lựa chọn cố định cho tham số đó. Ví dụ:

    parser.add_argument('role', choices=['Admin', 'Moderator', 'User'])
    
  • required: Có hay không tham số này bắt buộc phải được nhập.

  • help: Nội dung mô tả cho tham số này.

  • metavar: Tên cho tham số được sử dụng trong phần nội dung mô tả cho tham số.

  • dest: Tên biến sẽ nhận được giá trị của tham số này. Xem thêm tại ví dụ của store_truestore_false

Vậy là xong phần add_argument() method. Bây giờ chúng ta sang phần Action classes. Phần này sẽ giúp chúng ta định nghĩa riêng một action khác cho add_argument() method nhé 😄!

Action classes

argparse.Action(option_strings, dest, nargs=None, const=None, default=None, type=None, choices=None, required=False, help=None, metavar=None)

API này giúp chúng ta định nghĩa riêng một action khác cho add_argument() ngoài những action mặc định của nó như: store, store_const, store_true, store_false, append, append_const, count, help, version. Chúng ta thử đi luôn vào ví dụ nhé. Nếu ứng dụng của chúng ta cần nhận một tham số là password giống như MySQL vậy? Nhưng chúng ta không muốn khi người dùng nhập thì nó hiển thị raw text. Vậy chúng ta cần phải định nghĩa một action class cho phép ẩn những gì mà người dùng nhập đi. Chúng ta sẽ làm giống với MySQL nhé 😄! Trong action này có sử dụng module getpass.

mysql -uroot -p
Enter password:
#!/usr/bin/env python

# get-pass.py

import argparse
import getpass

class Password(argparse.Action):
    def __call__(self, parser, namespace, values, option_string):
        if values is None:
            values = getpass.getpass(prompt="Enter MySQL password: ")

        setattr(namespace, self.dest, values)

parser = argparse.ArgumentParser(description="Simple MySQL command-line :))")
parser.add_argument("-u", dest="username", help="Enter MySQL username")
parser.add_argument("-p", dest="password", help="Enter password for MySQL username", action=Password, nargs="?")

args = parser.parse_args()

print "Username: %s\nPassword: %s" % (args.username, args.password)

Bạn thử chạy chương trình với những lệnh sau xem sao nhé ^^:

  • python get-pass.py -uroot -p
  • python get-pass.py -uroot -p123456

Để có thể hiểu rõ hơn về Action class. Bạn có thể đọc thêm tại đây nhé. Giờ mình sẽ giới thiệu method mà nãy giờ có lẽ mọi người xem những ví dụ đều thấy cái mặt nó xuất hiện nhưng lại chưa thấy được nhắc đến ở đây. Đó là method parse_args() 😄!

Method parse_args()

Giúp chúng ta convert các tham số nhận được thành một object và gán nó thành một thuộc tính của một namespace.

ArgumentParser.parse_args(args=None, namespace=None)

Lời kết

Trên đây mình đã giới thiệu những method cơ bản của module Argparse. Đủ để giúp chúng ta có thể tạo ra 1 ứng dụng với nhiều tùy chọn phong phú 😄! Nếu bạn muốn nâng cao hơn, bạn có thể đọc thêm documentation của nó tại: https://docs.python.org/3/library/argparse.html. Hẹn gặp lại bạn ở bài viết sau. Mình sẽ giới thiệu về module BeautifulSoup - Một XML và HTML parser.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí