Nếu bạn lên kế hoạch cho một dự án khoa học dữ liệu hoặc học máy, thì việc bắt đầu phát triển trong một Jupyter Notebook là điều không hiếm gặp. Nó mang lại tính tương tác cho các công cụ tính toán của bạn, cho phép bạn chạy các mô-đun nhanh chóng, v.v. Có rất nhiều lý do để chọn Jupyter Notebook làm công cụ chủ lực, đặc biệt đối với các dự án khoa học dữ liệu hoặc học máy. Tuy nhiên, hướng dẫn này không nhằm bàn sâu về phần đó.
Giả sử bạn cần chạy một script Python như một tác vụ theo lô để nạp dữ liệu cho dự án khoa học dữ liệu của mình. Hoặc bạn cần chạy một script Python để triển khai một mô hình học máy lên máy chủ từ xa. Trong những trường hợp như vậy, chỉ chạy python your_script.py có thể là chưa đủ. Bạn có thể cần truyền thêm các tùy chọn hoặc đối số cùng với python your_script.py. Có thể bạn đã quen với việc dùng thêm đối số khi chạy các lệnh (như ps, ls, v.v.) trên terminal Linux.
Trong hướng dẫn này, bạn sẽ học cách phân tích các đối số, tùy chọn bổ sung từ dòng lệnh được truyền kèm theo một script Python. Dưới đây là tóm tắt nội dung cho hướng dẫn hôm nay:
Giới thiệu cơ bản về phân tích đối số
Phân tích đối số trong Python
Sử dụng sys.argv
Sử dụng getopt
Sử dụng argparse
Lưu ý hướng dẫn này giả định bạn đã quen thuộc cơ bản với Python.
Phân tích đối số là gì?
Nếu bạn là người dùng Linux, có lẽ bạn đã biết điều này rồi. Để lấy danh sách tóm tắt các tệp và thư mục trong một thư mục cụ thể, lệnh ls thường được sử dụng. Một đầu ra điển hình khi chạy lệnh ls trông như sau -
Tuy nhiên, bạn có thể cung cấp nhiều tùy chọn cho lệnh ls, ví dụ -l. Hãy xem đầu ra khi đó trông như thế nào -
Bằng cách truyền tùy chọn-l, bạn nhận được nhiều thông tin hơn. Giờ đây, có một khác biệt nhỏ giữa tùy chọn và đối số trong ngữ cảnh này. Để xóa một tệp hoặc thư mục khỏi thư mục làm việc hiện tại, lệnh rm thường được dùng. Giả sử bạn có một tệp văn bản tên demo.txt và bạn chạy rm demo.txt để xóa tệp. Trong trường hợp này, demo.txt là đối số mà bạn áp dụng cho lệnh rm. Nếu bạn không truyền bất kỳ đối số nào cho lệnh rm, bạn sẽ nhận lỗi như sau -
Vậy, sự khác nhau giữa một tùy chọn và một đối số là gì? Giờ thì khá rõ ràng: Tùy chọn là phần tùy ý truyền kèm, còn đối số thường là bắt buộc phải truyền. Không cần thiết phải truyền gì cho lệnh ls để nó tạo ra đầu ra.
Khi bạn gõ ls -l hoặc rm demo.txt, hệ điều hành sẽ phân tích theo một cách nhất định ở tầng bên dưới. Cơ chế này thường được các nhà phát triển hệ điều hành quy định, và được gọi là parsing (phân tích cú pháp).
Nếu bạn muốn biết thêm về các lệnh Linux và những tùy chọn, đối số mà chúng hỗ trợ, rất khuyến nghị đọc cuốn Unix Concepts and Applications.
Vừa rồi là phần giới thiệu cơ bản về phân tích đối số. Hầu như mọi ngôn ngữ lập trình đều hỗ trợ phân tích đối số. Python cũng không ngoại lệ. Có ba cách rất phổ biến để bạn thực hiện phân tích đối số trong Python -
sys.argv
getopt
argparse
Bây giờ bạn sẽ lần lượt xem từng lựa chọn trên và cách dùng chúng để phân tích đối số (và tùy chọn). Hãy đi theo trình tự thời gian.
Phân tích đối số bằng sys.argv
Bắt đầu đơn giản. Ở ví dụ đầu tiên này, bạn sẽ tạo một tệp Python tên demo1.py. Chương trình của bạn sẽ chấp nhận số lượng đối số tùy ý được truyền từ dòng lệnh (hoặc terminal) khi chạy. Chương trình sẽ in ra các đối số đã truyền và tổng số đối số.
Ví dụ, nếu bạn chạy python demo1.py abc 123, chương trình sẽ cho ra -
Number ofarguments:3Argument(s) passed:['demo1.py','abc','123']Được hỗ trợ bởi
Lưu ý đối số đầu tiên luôn là tên tệp Python. Nhưng bạn có thể sửa mã để loại trừ nó.
Bây giờ đến phần mã -
import sys
print('Number of arguments: {}'.format(len(sys.argv)))print('Argument(s) passed: {}'.format(str(sys.argv)))Được hỗ trợ bởi
Đầu tiên bạn import mô-đun Python sys, mô-đun đi kèm cài đặt chuẩn của Python. Sau đó bạn dùng thành phần argv trả về danh sách các đối số được truyền cho một script Python, trong đó argv[0] chứa tên script. Nếu bạn chạy sys.argv trong một ô mã như sau, bạn sẽ nhận được danh sách các tệp cấu hình chịu trách nhiệm giúp nhân IPython hoạt động đúng. Tốt hơn hết là không nên can thiệp vào chúng.
['/home/nbuser/anaconda3_501/lib/python3.6/site-packages/ipykernel/__main__.py','-f','/home/nbuser/.local/share/jupyter/runtime/kernel-dabba4f7-e3e0-4c39-99d2-261ba835c53f.json']Được hỗ trợ bởi
Giờ hãy xem cách dùng mô-đun getopt để phân tích đối số (và tùy chọn).
Phân tích đối số bằng getopt
So với sys.argv, mô-đun getopt linh hoạt hơn nhiều. Trước tiên hãy thiết kế một kịch bản mẫu và viết mã tương ứng.
Giả sử bạn đã phát hành một script Python nhưng chưa viết tài liệu. Tuy vậy, bạn muốn có thể cung cấp phản hồi hữu ích cho người dùng khi họ chạy script không đúng cách. Script Python của bạn thực hiện tác vụ đơn giản là cộng hai số và đưa ra kết quả. Ràng buộc duy nhất là người dùng cần truyền đầu vào dưới dạng đối số dòng lệnh kèm theo script.
Thực tế hơn một chút, script lý tưởng sẽ được chạy như sau -
python add_numbers.py -a 3 -b 8
Đầu ra nên là 11. Ở đây, -a và -b là các tùy chọn, và 3, 8 là các đối số bạn cung cấp cho script. Các tùy chọn không chỉ giúp tăng tính dễ đọc mà còn hỗ trợ quyết định luồng xử lý (hãy hình dung nếu bạn thực hiện phép chia thay vì phép cộng). Bắt đầu xem mã cho phần này.
import getopt
import sys
# Get the arguments from the command-line except the filename
argv = sys.argv[1:]sum=0try:# Define the getopt parameters
opts, args = getopt.getopt(argv,'a:b:',['foperand','soperand'])# Check if the options' length is 2 (can be enhanced)iflen(opts)==0andlen(opts)>2:print('usage: add.py -a <first_operand> -b <second_operand>')else:# Iterate the options and get the corresponding valuesfor opt, arg in opts:sum+=int(arg)print('Sum is {}'.format(sum))except getopt.GetoptError:# Print something usefulprint('usage: add.py -a <first_operand> -b <second_operand>')
sys.exit(2)Được hỗ trợ bởi
Ý tưởng là đầu tiên lấy tất cả đối số bằng sys.argv rồi xử lý tương ứng. Giờ đến dòng mã quan trọng nhất - opts, args = getopt.getopt(argv, 'a:b:', ['foperand', 'soperand'])
Chữ ký của phương thức getopt() trông như sau:
getopt.getopt(args, shortopts, longopts=[])
args là danh sách đối số lấy từ dòng lệnh.
shortopts là nơi bạn chỉ định các chữ cái đại diện cho tùy chọn. Nếu bạn cung cấp a:, nghĩa là script của bạn nên được truyền tùy chọn a theo sau là một giá trị làm đối số. Về mặt kỹ thuật, bạn có thể dùng bao nhiêu tùy chọn tùy ý ở đây. Khi truyền các tùy chọn từ dòng lệnh, chúng phải có tiền tố '-'.
longopts là nơi bạn có thể chỉ định dạng mở rộng của shortopts. Chúng phải có tiền tố '--'.
Bạn định nghĩa shortopts là a:b: nghĩa là script Python của bạn sẽ nhận hai tùy chọn dạng chữ cái - 'a' và 'b'. Bằng cách thêm dấu ':' bạn nói rõ rằng các tùy chọn này sẽ theo sau bởi các đối số.
Bạn định nghĩa longopts là ['foperand', 'soperand'] tức là chấp nhận f_operand và s_operand thay cho a và b làm tùy chọn. Nhưng chúng luôn phải theo sau --.
Mô-đun getopt cũng cung cấp lớp ngoại lệ tiện dụng GetoptError để định nghĩa các thông điệp hữu ích, nhằm hướng dẫn người dùng cách sử dụng script Python của bạn. Đó là lý do bạn bọc phần chức năng của script trong khối try và định nghĩa khối except tương ứng.
Đây là cách bạn có thể chạy script Python:
Lưu ý rằng script trên không được định nghĩa để xử lý longopts. Đây là điều bạn có thể thử như một bài tập.
Giờ hãy xem cách dùng argparse để phân tích đối số.
Phân tích đối số bằng argparse
Từ hai lựa chọn ở trên, có thể thấy chúng không thật sự dễ đọc. Khi thấy argparse hoạt động, bạn cũng sẽ đồng ý rằng hai lựa chọn trên thiếu linh hoạt. Để hiểu cách dùng argparse, hãy bắt đầu với một đoạn mã triển khai kịch bản bạn vừa thấy ở phần trên.
import argparse
# Construct the argument parser
ap = argparse.ArgumentParser()# Add the arguments to the parser
ap.add_argument("-a","--foperand", required=True,help="first operand")
ap.add_argument("-b","--soperand", required=True,help="second operand")
args =vars(ap.parse_args())# Calculate the sumprint("Sum is {}".format(int(args['foperand'])+int(args['soperand'])))Được hỗ trợ bởi
Trước hết, argparse cũng như hai mô-đun đã thảo luận ở trên, đều đi kèm cài đặt chuẩn của Python. Bạn bắt đầu bằng cách khởi tạo đối tượng argparse. Phần còn lại trở nên rất dễ viết. Lấy ví dụ dòng mã sau -
Ở đây bạn thêm đối số mà bạn kỳ vọng sẽ được truyền kèm khi chạy script Python. Bạn cung cấp dạng chữ cái của đối số cùng với dạng mở rộng. Bằng cách chỉ định required=True bạn yêu cầu rõ ràng người dùng phải truyền đối số đó. Cuối cùng, bạn thêm mô tả có ý nghĩa cho đối số, sẽ được hiển thị cho người dùng nếu họ không chạy script đúng cách.
Phần định nghĩa đối số cũng tương tự cho đối số thứ hai. Bạn truy cập các đối số đã cho bằng cách chỉ định chỉ mục tương ứng của chúng.
Đoạn mã trên cho thấy rõ việc định nghĩa các tác vụ phân tích đối số dòng lệnh với argparse dễ dàng và linh hoạt thế nào. Đây là cách bạn có thể thử nghiệm với script Python trên:
Hãy chú ý quy trình trở nên dễ dàng hơn nhiều với argparse.
Tiếp theo là gì?
Cảm ơn bạn đã đọc đến cuối hướng dẫn hôm nay. Giờ đây, bạn đã trang bị cho mình các mô-đun Python gốc có thể phân tích các đối số được truyền từ dòng lệnh cùng với script Python của bạn. Như một bài tập, bạn có thể tùy chỉnh các dự án học máy và khoa học dữ liệu của mình để hỗ trợ phân tích đối số và biến chúng thành các tiện ích script hữu ích. Không chỉ trong học máy hay khoa học dữ liệu, mà ở bất kỳ đâu bạn thấy phù hợp. Đó là tất cả cho hướng dẫn hôm nay. Nếu bạn muốn nâng cao kỹ năng Python, bạn có thể tham khảo khóa học Python Data Science Toolbox (Phần 1) của DataCamp.
Nếu bạn lên kế hoạch cho một dự án khoa học dữ liệu hoặc học máy, thì việc bắt đầu phát triển trong một Jupyter Notebook là điều không hiếm gặp. Nó mang lại tính tương tác cho các công cụ tính toán của bạn, cho phép bạn chạy các mô-đun nhanh chóng, v.v. Có rất nhiều lý do để chọn Jupyter Notebook làm công cụ chủ lực, đặc biệt đối với các dự án khoa học dữ liệu hoặc học máy. Tuy nhiên, hướng dẫn này không nhằm bàn sâu về phần đó.
Giả sử bạn cần chạy một script Python như một tác vụ theo lô để nạp dữ liệu cho dự án khoa học dữ liệu của mình. Hoặc bạn cần chạy một script Python để triển khai một mô hình học máy lên máy chủ từ xa. Trong những trường hợp như vậy, chỉ chạy
python your_script.pycó thể là chưa đủ. Bạn có thể cần truyền thêm các tùy chọn hoặc đối số cùng vớipython your_script.py. Có thể bạn đã quen với việc dùng thêm đối số khi chạy các lệnh (nhưps,ls, v.v.) trên terminal Linux.Trong hướng dẫn này, bạn sẽ học cách phân tích các đối số, tùy chọn bổ sung từ dòng lệnh được truyền kèm theo một script Python. Dưới đây là tóm tắt nội dung cho hướng dẫn hôm nay:
sys.argvgetoptargparseLưu ý hướng dẫn này giả định bạn đã quen thuộc cơ bản với Python.
Phân tích đối số là gì?
Nếu bạn là người dùng Linux, có lẽ bạn đã biết điều này rồi. Để lấy danh sách tóm tắt các tệp và thư mục trong một thư mục cụ thể, lệnh
lsthường được sử dụng. Một đầu ra điển hình khi chạy lệnhlstrông như sau -Tuy nhiên, bạn có thể cung cấp nhiều tùy chọn cho lệnh
ls, ví dụ-l. Hãy xem đầu ra khi đó trông như thế nào -Bằng cách truyền tùy chọn
-l, bạn nhận được nhiều thông tin hơn. Giờ đây, có một khác biệt nhỏ giữa tùy chọn và đối số trong ngữ cảnh này. Để xóa một tệp hoặc thư mục khỏi thư mục làm việc hiện tại, lệnhrmthường được dùng. Giả sử bạn có một tệp văn bản têndemo.txtvà bạn chạyrm demo.txtđể xóa tệp. Trong trường hợp này,demo.txtlà đối số mà bạn áp dụng cho lệnhrm. Nếu bạn không truyền bất kỳ đối số nào cho lệnhrm, bạn sẽ nhận lỗi như sau -Vậy, sự khác nhau giữa một tùy chọn và một đối số là gì? Giờ thì khá rõ ràng: Tùy chọn là phần tùy ý truyền kèm, còn đối số thường là bắt buộc phải truyền. Không cần thiết phải truyền gì cho lệnh
lsđể nó tạo ra đầu ra.Khi bạn gõ
ls -lhoặcrm demo.txt, hệ điều hành sẽ phân tích theo một cách nhất định ở tầng bên dưới. Cơ chế này thường được các nhà phát triển hệ điều hành quy định, và được gọi là parsing (phân tích cú pháp).Nếu bạn muốn biết thêm về các lệnh Linux và những tùy chọn, đối số mà chúng hỗ trợ, rất khuyến nghị đọc cuốn Unix Concepts and Applications.
Vừa rồi là phần giới thiệu cơ bản về phân tích đối số. Hầu như mọi ngôn ngữ lập trình đều hỗ trợ phân tích đối số. Python cũng không ngoại lệ. Có ba cách rất phổ biến để bạn thực hiện phân tích đối số trong Python -
Bây giờ bạn sẽ lần lượt xem từng lựa chọn trên và cách dùng chúng để phân tích đối số (và tùy chọn). Hãy đi theo trình tự thời gian.
Phân tích đối số bằng sys.argv
Bắt đầu đơn giản. Ở ví dụ đầu tiên này, bạn sẽ tạo một tệp Python tên
demo1.py. Chương trình của bạn sẽ chấp nhận số lượng đối số tùy ý được truyền từ dòng lệnh (hoặc terminal) khi chạy. Chương trình sẽ in ra các đối số đã truyền và tổng số đối số.Ví dụ, nếu bạn chạy
python demo1.py abc 123, chương trình sẽ cho ra -Lưu ý đối số đầu tiên luôn là tên tệp Python. Nhưng bạn có thể sửa mã để loại trừ nó.
Bây giờ đến phần mã -
Đầu tiên bạn import mô-đun Python
sys, mô-đun đi kèm cài đặt chuẩn của Python. Sau đó bạn dùng thành phầnargvtrả về danh sách các đối số được truyền cho một script Python, trong đóargv[0]chứa tên script. Nếu bạn chạysys.argvtrong một ô mã như sau, bạn sẽ nhận được danh sách các tệp cấu hình chịu trách nhiệm giúp nhân IPython hoạt động đúng. Tốt hơn hết là không nên can thiệp vào chúng.Giờ hãy xem cách dùng mô-đun
getoptđể phân tích đối số (và tùy chọn).Phân tích đối số bằng getopt
So với
sys.argv, mô-đungetoptlinh hoạt hơn nhiều. Trước tiên hãy thiết kế một kịch bản mẫu và viết mã tương ứng.Giả sử bạn đã phát hành một script Python nhưng chưa viết tài liệu. Tuy vậy, bạn muốn có thể cung cấp phản hồi hữu ích cho người dùng khi họ chạy script không đúng cách. Script Python của bạn thực hiện tác vụ đơn giản là cộng hai số và đưa ra kết quả. Ràng buộc duy nhất là người dùng cần truyền đầu vào dưới dạng đối số dòng lệnh kèm theo script.
Thực tế hơn một chút, script lý tưởng sẽ được chạy như sau -
python add_numbers.py -a 3 -b 8Đầu ra nên là 11. Ở đây,
-avà-blà các tùy chọn, và 3, 8 là các đối số bạn cung cấp cho script. Các tùy chọn không chỉ giúp tăng tính dễ đọc mà còn hỗ trợ quyết định luồng xử lý (hãy hình dung nếu bạn thực hiện phép chia thay vì phép cộng). Bắt đầu xem mã cho phần này.Ý tưởng là đầu tiên lấy tất cả đối số bằng
sys.argvrồi xử lý tương ứng. Giờ đến dòng mã quan trọng nhất -opts, args = getopt.getopt(argv, 'a:b:', ['foperand', 'soperand'])Chữ ký của phương thức
getopt()trông như sau:getopt.getopt(args, shortopts, longopts=[])argslà danh sách đối số lấy từ dòng lệnh.shortoptslà nơi bạn chỉ định các chữ cái đại diện cho tùy chọn. Nếu bạn cung cấpa:, nghĩa là script của bạn nên được truyền tùy chọnatheo sau là một giá trị làm đối số. Về mặt kỹ thuật, bạn có thể dùng bao nhiêu tùy chọn tùy ý ở đây. Khi truyền các tùy chọn từ dòng lệnh, chúng phải có tiền tố '-'.longoptslà nơi bạn có thể chỉ định dạng mở rộng củashortopts. Chúng phải có tiền tố '--'.Bạn định nghĩa
shortoptslàa:b:nghĩa là script Python của bạn sẽ nhận hai tùy chọn dạng chữ cái - 'a' và 'b'. Bằng cách thêm dấu ':' bạn nói rõ rằng các tùy chọn này sẽ theo sau bởi các đối số.Bạn định nghĩa
longoptslà['foperand', 'soperand']tức là chấp nhậnf_operandvàs_operandthay choavàblàm tùy chọn. Nhưng chúng luôn phải theo sau--.Mô-đun
getoptcũng cung cấp lớp ngoại lệ tiện dụngGetoptErrorđể định nghĩa các thông điệp hữu ích, nhằm hướng dẫn người dùng cách sử dụng script Python của bạn. Đó là lý do bạn bọc phần chức năng của script trong khốitryvà định nghĩa khốiexcepttương ứng.Đây là cách bạn có thể chạy script Python:
Lưu ý rằng script trên không được định nghĩa để xử lý
longopts. Đây là điều bạn có thể thử như một bài tập.Giờ hãy xem cách dùng
argparseđể phân tích đối số.Phân tích đối số bằng argparse
Từ hai lựa chọn ở trên, có thể thấy chúng không thật sự dễ đọc. Khi thấy
argparsehoạt động, bạn cũng sẽ đồng ý rằng hai lựa chọn trên thiếu linh hoạt. Để hiểu cách dùngargparse, hãy bắt đầu với một đoạn mã triển khai kịch bản bạn vừa thấy ở phần trên.Trước hết,
argparsecũng như hai mô-đun đã thảo luận ở trên, đều đi kèm cài đặt chuẩn của Python. Bạn bắt đầu bằng cách khởi tạo đối tượngargparse. Phần còn lại trở nên rất dễ viết. Lấy ví dụ dòng mã sau -ap.add_argument("-a", "--foperand", required=True, help="first operand")Ở đây bạn thêm đối số mà bạn kỳ vọng sẽ được truyền kèm khi chạy script Python. Bạn cung cấp dạng chữ cái của đối số cùng với dạng mở rộng. Bằng cách chỉ định
required=Truebạn yêu cầu rõ ràng người dùng phải truyền đối số đó. Cuối cùng, bạn thêm mô tả có ý nghĩa cho đối số, sẽ được hiển thị cho người dùng nếu họ không chạy script đúng cách.Phần định nghĩa đối số cũng tương tự cho đối số thứ hai. Bạn truy cập các đối số đã cho bằng cách chỉ định chỉ mục tương ứng của chúng.
Đoạn mã trên cho thấy rõ việc định nghĩa các tác vụ phân tích đối số dòng lệnh với
argparsedễ dàng và linh hoạt thế nào. Đây là cách bạn có thể thử nghiệm với script Python trên:Hãy chú ý quy trình trở nên dễ dàng hơn nhiều với
argparse.Tiếp theo là gì?
Cảm ơn bạn đã đọc đến cuối hướng dẫn hôm nay. Giờ đây, bạn đã trang bị cho mình các mô-đun Python gốc có thể phân tích các đối số được truyền từ dòng lệnh cùng với script Python của bạn. Như một bài tập, bạn có thể tùy chỉnh các dự án học máy và khoa học dữ liệu của mình để hỗ trợ phân tích đối số và biến chúng thành các tiện ích script hữu ích. Không chỉ trong học máy hay khoa học dữ liệu, mà ở bất kỳ đâu bạn thấy phù hợp. Đó là tất cả cho hướng dẫn hôm nay. Nếu bạn muốn nâng cao kỹ năng Python, bạn có thể tham khảo khóa học Python Data Science Toolbox (Phần 1) của DataCamp.