Tin tức và phân tích của tất cả các thiết bị di động

Cách phân tích các đối số dòng lệnh trong python

Bạn muốn chạy tập lệnh python với đối số dòng lệnh? Tìm hiểu cách phân tích cú pháp các đối số dòng lệnh bằng các mô-đun sys, getopt và argparse trong Python.

Trong Python, khi bạn muốn đọc dữ liệu đầu vào của người dùng, bạn sử dụng hàm input(). Tuy nhiên, đối với một số ứng dụng, bạn có thể muốn truyền một số đối số nhất định khi chạy tập lệnh trên dòng lệnh.

Trong hướng dẫn này, chúng ta sẽ tìm hiểu cách chạy tập lệnh Python với các tùy chọn và đối số trên dòng lệnh. Tiếp theo, chúng ta sẽ tìm hiểu cách sử dụng các mô-đun tích hợp sẵn của Python để phân tích các tùy chọn và đối số đó.

Hãy bắt đầu!

Hiểu sys.argv trong Python

Nếu bạn đã lập trình bằng C, bạn biết rằng một trong những cách dễ nhất để truyền đối số cho chương trình là bằng dòng lệnh. Để làm điều này, bạn có thể cấu trúc hàm main như thế này:

#include<stdio.h>

int main(int argc, char **argv){
    //argc: argument count
    //argv: argument vector
    
    //do something on the args

    return 0;
}

Ở đây argc là số lượng đối số và argv là một vectơ đối số.

Chạy tập lệnh python với đối số dòng lệnh

Trong python, bạn có thể chạy tập lệnh python trên dòng lệnh bằng cách sử dụng python3 filename.py. Trong khi thực hiện việc này, bạn cũng có thể chuyển bất kỳ số lượng đối số dòng lệnh nào:

$ python3 filename.py arg1 arg2 ... argn

Mô-đun sys cung cấp hỗ trợ ngay lập tức để truy cập và xử lý các đối số dòng lệnh này. sys.argv là danh sách tất cả các đối số dòng lệnh mà chúng tôi chuyển qua khi chạy tập lệnh python.

Đây là một ví dụ nơi chúng tôi chạy main.py với các đối số dòng lệnh:

$ python3 main.py hello world python script

Chúng ta có thể lặp qua một vectơ đối số bằng vòng lặp for đơn giản và hàm liệt kê:

# main.py

import sys

for idx, arg in enumerate(sys.argv):
    print(f"arg{idx}: {arg}")
# Output
arg0:main.py
arg1:hello
arg2:world
arg3:python
arg4:script

Chúng ta thấy rằng đối số đầu tiên (trong chỉ mục 0) là tên tệp python. Các đối số tiếp theo bắt đầu bằng chỉ mục 1.

Đây là một chương trình làm việc tối thiểu chấp nhận và xử lý các đối số dòng lệnh. Tuy nhiên, chúng tôi thấy có một số vấn đề:

  • Làm thế nào để người dùng chương trình biết những đối số nào cần chuyển?
  • Và tại sao lại có những lập luận này?

Nó không rõ ràng lắm. Bạn có thể sử dụng mô-đun getopt hoặc argparse để giải quyết vấn đề này. Và chúng ta sẽ tìm hiểu ở những phần sau. ✅

Phân tích đối số dòng lệnh bằng getopt

Hãy tìm hiểu cách phân tích các đối số dòng lệnh bằng mô-đun getopt tích hợp.

Sau khi nhập getopt từ mô-đun getopt, bạn có thể chỉ định các đối số để phân tích cú pháp cũng như các tùy chọn ngắn và dài để chạy tập lệnh. Chúng ta cần phân tích tất cả các đối số bắt đầu bằng chỉ mục 1 trong sys.argv. Vậy lát cắt cần phân tích là sys.argv[1:].

Ở đây chúng ta sẽ cần chuỗi thông báo và tên tệp. Hãy sử dụng mif làm tùy chọn ngắn và tin nhắn và tệp làm tùy chọn dài.

Nhưng làm thế nào để bạn chắc chắn rằng một tùy chọn cụ thể cần có một đối số?

  • Trong các tùy chọn ngắn, bạn có thể tạo một tùy chọn yêu cầu đối số bằng cách thêm dấu hai chấm (:) sau tên tùy chọn ngắn.
  • Tương tự, trong các tùy chọn dài, bạn có thể thêm dấu = sau một tùy chọn dài. Chúng ta có thể nắm bắt các tùy chọn này và các đối số tương ứng của chúng.

Thêm chúng, chúng ta sẽ có đoạn mã sau trong main.py:

# main.py

import sys
from getopt import getopt

opts, args = getopt(sys.argv[1:],'m:f:',['message=","file="])

print(opts)
print(args)

Ở đây biến opts chứa các tùy chọn và đối số dưới dạng danh sách các bộ dữ liệu. Bất kỳ đối số vị trí nào khác mà chúng tôi chuyển qua sẽ được thu thập trong đối số.

Chúng ta có thể chuyển một thông báo và tên tệp để chạy tập lệnh và chúng ta có thể sử dụng các tùy chọn ngắn hoặc dài.

Chạy main.py bằng các tùy chọn dài, chúng tôi có:

$ python3 main.py --message hello --file somefile.txt

Chúng tôi có các tùy chọn và đối số dưới dạng bộ dữ liệu trong biến opts. Vì chúng ta không chuyển bất kỳ đối số vị trí nào nên args là một danh sách trống.

# Output
[("--message', 'hello'), ('--file', 'somefile.txt')]
[]

Tương tự, chúng ta cũng có thể sử dụng các tùy chọn ngắn như hình:

$ python3 main.py -m hello -f somefile.txt
# Output
[('-m', 'hello'), ('-f', 'somefile.txt')]
[]

⚠️ Không nên nhầm lẫn tùy chọn -m short trong ví dụ này với cờ dòng lệnh -m, được sử dụng để chạy mô-đun làm mô-đun chính khi chạy tập lệnh python.

Ví dụ: bạn sẽ sử dụng python3 -m unittest main.py để chạy unittest làm mô-đun chính khi chạy main.py.

Chúng tôi đã đề cập rằng tất cả các đối số vị trí khác mà chúng tôi chuyển qua sẽ được lưu trữ trong args. Đây là một ví dụ:

$ python3 main.py -m hello -f somefile.txt another_argument

Danh sách đối số chứa đối số vị trí other_argument.

# Output
[('-m', 'hello'), ('-f', 'somefile.txt')]
['another_argument']

Ở đây opts là danh sách các bộ dữ liệu. Vì vậy, chúng ta có thể lặp qua nó, giải nén bộ dữ liệu và lấy ra các đối số tương ứng với các tùy chọn đã chỉ định.

Nhưng chúng ta phải làm gì với tên tệp và thông báo sau khi xử lý các đối số này? Chúng ta sẽ mở file ở chế độ ghi và ghi chuỗi thông báo đã chuyển sang chữ hoa vào file.

# main.py
import sys
from getopt import getopt

opts, args = getopt(sys.argv[1:],'m:f:',['message=","file="])

print(opts)
print(args)

for option, argument in opts:
    if option == "-m':
        message = argument
    if option == '-f':
        file = argument

with open(file,'w') as f:
    f.write(message.upper())

Hãy chạy main.py với các tùy chọn ngắn và đối số dòng lệnh.

$ python main.py -m hello -f thisfile.txt
[('-m', 'hello'), ('-f', 'thisfile.txt')]
[]

Sau khi chạy main.py, chúng ta có thể thấy “thisfile.txt” trong thư mục làm việc của mình. Chứa chuỗi “hello” được chuyển thành chữ hoa (“HELLO”).

$ ls
main.py  thisfile.txt
$ cat thisfile.txt
HELLO

Cách phân tích các đối số dòng lệnh bằng Argparse

Mô-đun argparse, cũng được tích hợp trong thư viện chuẩn Python, cung cấp chức năng phân tích cú pháp các đối số dòng lệnh cũng như xây dựng giao diện dòng lệnh.

Để phân tích các đối số dòng lệnh, hãy nhập lớp ArgumentParser từ mô-đun argparse. Ở đây chúng ta đã khởi tạo arg_parser, đối tượng ArgumentParser:

from argparse import ArgumentParser

arg_parser = ArgumentParser()

Tiếp theo, chúng tôi muốn thêm hai đối số dòng lệnh:

  • tin nhắn: chuỗi tin nhắn i
  • file: tên của file chúng ta muốn làm việc.

Bây giờ chúng ta gọi add_argument() trên arg_parser để thêm cả hai đối số. Khi gọi phương thức add_argument(), bạn có thể đặt trợ giúp thành một chuỗi (mô tả đối số).

arg_parser.add_argument('message',help='message string')
arg_parser.add_argument('file',help='filename')

Cho đến nay chúng ta đã tạo một phiên bản arg_parser và thêm các đối số dòng lệnh. Khi chương trình được chạy từ dòng lệnh, bạn có thể sử dụng phương thức extract_args() trên arg_parser để lấy các giá trị của các đối số.

Ở đây chúng ta nắm bắt được không gian tên của các đối số trong biến args. Vì vậy bạn có thể sử dụng args.argument_name để lấy các giá trị của các đối số.

Sau khi truy xuất các giá trị của các đối số, chúng ta viết chuỗi thông báo hoán đổi chữ hoa chữ thường (sử dụng phương thức chuỗi swapcase()) vào một tệp.

args = arg_parser.parse_args()

message = args.message
file = args.file

with open(file,'w') as f:
     f.write(message.swapcase())

Đặt tất cả lại với nhau, đây là tệp main.py của chúng tôi:

# main.py

from argparse import ArgumentParser

arg_parser = ArgumentParser()
arg_parser.add_argument('message',help='message string')
arg_parser.add_argument('file',help='filename')

args = arg_parser.parse_args()
print(args)

message = args.message
file = args.file

with open(file,'w') as f:
     f.write(message.swapcase())

Hiểu cách sử dụng các đối số dòng lệnh

Để hiểu cách sử dụng các đối số khi chạy main.py, bạn có thể sử dụng tùy chọn -help long như minh họa:

$ python3 main.py --help
usage: main.py [-h] message file

positional arguments:
  message     message string
  file        filename

optional arguments:
  -h, --help  show this help message and exit

Không có đối số tùy chọn và cả tin nhắn và tệp đều là đối số vị trí bắt buộc. Ngoài ra, bạn cũng có thể sử dụng tùy chọn -h ngắn:

$ python3 main.py -h
usage: main.py [-h] message file

positional arguments:
  message     message string
  file        filename

optional arguments:
  -h, --help  show this help message and exit

Như bạn có thể thấy, cả hai đối số đều là đối số vị trí theo mặc định. Vì vậy, nếu bạn không vượt qua một hoặc nhiều đối số này, bạn sẽ gặp lỗi.

Ở đây, chúng tôi đã chuyển đối số vị trí (Xin chào) cho chuỗi thông báo, nhưng chúng tôi không chuyển bất kỳ giá trị nào cho đối số tệp.

Và tôi gặp lỗi khi nói rằng đối số tệp là bắt buộc.

$ python3 main.py Hello
usage: main.py [-h] message file
main.py: error: the following arguments are required: file

Khi chạy main.py với cả hai đối số vị trí, chúng ta sẽ thấy vùng tên args chứa các giá trị đối số.

$ python3 main.py Hello file1.txt
# Output
Namespace(file="file1.txt", message="Hello")

Bây giờ, nếu nhìn vào nội dung của thư mục làm việc hiện tại, chúng ta có thể thấy tập lệnh tạo tệp “file1.txt”:

$ ls
file1.txt  main.py

Chuỗi tin nhắn ban đầu là “Xin chào”; không phân biệt chữ hoa chữ thường, chuỗi thông báo trong “file1.txt” là “hELLO”.

$ cat file1.txt
hELLO

Cách tạo đối số dòng lệnh tùy chọn

Để làm cho các đối số dòng lệnh này trở thành tùy chọn, bạn có thể đặt tiền tố tên đối số bằng ký tự –.

Hãy sửa đổi tệp main.py để cả đối số thông báo và tệp đều là tùy chọn.

# main.py

from argparse import ArgumentParser

arg_parser = ArgumentParser()
arg_parser.add_argument('--message',help='message string')
arg_parser.add_argument('--file',help='filename')

Vì cả hai đối số dòng lệnh đều là tùy chọn nên chúng ta có thể đặt giá trị mặc định cho các đối số này.

if args.message and args.file:
    message = args.message
    file = args.file
else:
    message="Python3"
    file="myfile.txt"

Tại thời điểm này, main.py chứa đoạn mã sau:

# main.py

from argparse import ArgumentParser

arg_parser = ArgumentParser()
arg_parser.add_argument('--message',help='message string')
arg_parser.add_argument('--file',help='filename')

args = arg_parser.parse_args()
print(args)

if args.message and args.file:
    message = args.message
    file = args.file
else:
    message="Python3"
    file="myfile.txt"

with open(file,'w') as f:
     f.write(message.swapcase())

Nếu kiểm tra cách sử dụng, chúng tôi thấy rằng cả tin nhắn và tệp đều là đối số tùy chọn. Điều này có nghĩa là bây giờ bạn có thể chạy main.py mà không cần cả hai đối số này.

$ python3 main.py --help
usage: main.py [-h] [--message MESSAGE] [--file FILE]

optional arguments:
  -h, --help         show this help message and exit
  --message MESSAGE  message string
  --file FILE        filename
$ python3 main.py

Trong không gian tên đối số, cả tệp và tin nhắn đều là Không.

# Output
Namespace(file=None, message=None)

Chúng ta có thể thấy tên tệp mặc định được sử dụng và thông báo “myfile.txt” và “Python3”. Tệp “myfile.txt” hiện có trong thư mục làm việc:

$ ls
file1.txt  main.py  myfile.txt

Và nó chứa chuỗi “Python3” với các chữ cái được hoán đổi:

$ cat myfile.txt
pYTHON3

Bạn cũng có thể sử dụng cả đối số –message và –file để làm cho lệnh dễ đọc hơn.

$ python3 main.py --message Coding --file file2.txt
# Output
Namespace(file="file2.txt", message="Coding")

Chúng tôi thấy “file2.txt” trong thư mục làm việc:

$ ls
file1.txt  file2.txt  main.py  myfile.txt

Và đúng như mong đợi, nó chứa chuỗi “coDING”.

$ cat file2.txt
cODING

Ứng dụng

Dưới đây là tóm tắt những gì chúng ta đã học được trong hướng dẫn này:

  • Tương tự như ngôn ngữ lập trình C, các đối số dòng lệnh có thể được truy cập bằng Python bằng cách duyệt qua vectơ đối số sys.argv. sys.argv[0] là tên của tập lệnh python. Vì vậy, chúng tôi quan tâm đến việc phân tích các đối số sys.argv[1:].
  • Tuy nhiên, để tăng khả năng đọc và có thể thêm tùy chọn, bạn có thể sử dụng mô-đun getopt và argparse.
  • Bạn có thể sử dụng mô-đun getopt để phân tích danh sách các đối số dòng lệnh bắt đầu từ chỉ mục 1 cho đến hết danh sách. Bạn có thể chỉ định cả tùy chọn ngắn và dài.
  • Khi một tùy chọn nhận một đối số, bạn có thể chỉ định dấu hai chấm (:) và = sau tùy chọn ngắn và tùy chọn dài tương ứng.
  • Với mô-đun argparse Python, bạn có thể khởi tạo một đối tượng ArgumentParser và sử dụng phương thức add_argument() để thêm đối số vị trí cần thiết. Sử dụng – trước tên đối số để biến nó thành tùy chọn.
  • Để truy xuất các giá trị của đối số dòng lệnh, hãy gọi phương thức pars_args() trên đối tượng ArgumentParser.

Sau đó tìm hiểu cách băm an toàn trong Python.