Nhiều con trăn argparse
Các công cụ Giao diện dòng lệnh (cli) là bánh mì và bơ của các nhà khoa học dữ liệu khi yêu cầu của họ vượt xa những gì máy tính xách tay Jupyter có thể cung cấp. Python argparse từ thư viện chuẩn là công cụ đầu tiên chúng tôi gặp trong hành trình Python của mình để xây dựng các giao diện như vậy một cách dễ dàng. Tuy nhiên, mặc dù có thể dễ dàng xây dựng một cli nhỏ dễ sử dụng với argparse chỉ bằng ba phương thức của lớp ArgumentParser, nhưng cần có một số kế hoạch bổ sung khi giao diện phát triển và trở nên phức tạp hơn. Trong bài viết này, chúng tôi khám phá các phương pháp để chia cli của chúng tôi thành các lệnh phụ riêng biệt với các đối số có thể được tải trong thời gian chạy, cũng như cách kết hợp chúng với các mẫu thiết kế để mở rộng nó dễ dàng hơn Show Hầu hết các công cụ cli cung cấp nhiều lệnh, mỗi lệnh có bộ đối số riêng. Hãy lấy git làm ví dụ, sau đây là danh sách tất cả các lệnh git bạn có thể chạy $ git --help và đây là những lập luận cho một số trong số họ $ git add --helpSYNOPSISgit add [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p] [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]] [--sparse] [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [-renormalize] [--chmod=(+|-)x] [--pathspec-from-file= Bạn có thể thấy rằng chúng trùng nhau nhưng không giống nhau. Nếu bạn cố gắng sử dụng một lệnh có đối số từ một lệnh khác thì rõ ràng là nó sẽ bị lỗi $ git add --reset-author Giả sử bạn đang viết một công cụ cli cho công việc khoa học dữ liệu của mình bằng Python, có thể bạn đang viết một công cụ để giải quyết các vấn đề trong miền của mình bằng học sâu Chọn công cụ học sâu của bạnTại sao công cụ của bạn có thể phụ thuộc vào cấu trúc nhóm của tổ chức bạnhướng tới khoa học dữ liệu. com thì rất có thể bạn sẽ viết cli của mình bằng argparse từ thư viện chuẩn, vì nó có thể không phải là tốt nhất cho mục đích này nhưng chắc chắn đây là cái đầu tiên bạn học Xây dựng một trình phân tích cú pháp đối số để sử dụng các lệnh phụ khá đơn giản và chúng tôi sẽ minh họa bằng một ví dụ. Chúng tôi có ứng dụng ví dụ của mình, với các lệnh đào tạo và suy luận, mỗi lệnh có các đối số khác nhau có thể là bắt buộc hoặc tùy chọn. Mã ví dụ có sẵn tại https. //github. com/mattiadg/example-cli và sao chép ở đây để thuận tiện # src/sub_commands.pyimport argparse Các Subparsers từ argparse sẽ thực hiện công việc. Trước tiên, chúng tôi cần tuyên bố rằng chúng tôi muốn sử dụng các bộ phân tích con với subparsers = parser.add_subparsers(help="Sub-commands help") Sau đó, chúng ta khai báo các bộ phân tích con cho các lệnh “train” và “infer” bằng phương thức add_parser() parser_train = subparsers.add_parser("train", help="Train a model") Sau đó, các trình phân tích cú pháp con sẽ hoạt động chính xác như bất kỳ trình phân tích cú pháp nào khác. Hãy kiểm tra cli của chúng tôi $ python .\src\sub_commands.py train -m transformer --save_model_path $HOME/my_model_path/ Và nó sẽ không chấp nhận các đối số cụ thể để suy luận $ python .\src\correct.py train -m transformer --save_model_path $HOME/my_model_path/ --model_path . Nhưng — model_path hoạt động chính xác khi sử dụng lệnh “suy luận” $ python .\src\correct.py infer --model_path $HOME/my_model_path/ Đối số độngBây giờ, chúng tôi muốn chỉ định một số đối số cho các mô hình mà chúng tôi muốn đào tạo. Trong ví dụ của chúng tôi, chúng tôi có hai mô hình khác nhau, máy biến áp và lstm. Lstm có các tham số là kích thước của vectơ đầu ra và kích thước của vectơ trạng thái. Máy biến áp có kích thước của các lớp con và kích thước khác nhau cho lớp con chuyển tiếp lớn. Cả hai loại mô hình đều có số lớp làm đối số Tôi không tìm thấy cách đính kèm trình phân tích cú pháp phụ vào giá trị của một đối số được đặt tên như mô hình, vì vậy chúng tôi phải đi theo một lộ trình khác Đầu tiên, để giữ cho mã trình phân tích cú pháp có thể quản lý được, chúng tôi không muốn tất cả các đối số hiển thị trong cùng một tệp chính. Chúng tôi sẽ giữ các đối số mới trong các tệp nơi chúng tôi xác định các mô hình tương ứng bằng cách sử dụng hàm lấy trình phân tích cú pháp làm đầu vào và thêm các đối số mới Đây là giao diện của Lstm # src/models/lstm.pydef add_arguments(parser): Và sau đây cho máy biến áp $ git add --helpSYNOPSISgit add [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p] [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]] [--sparse] [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [-renormalize] [--chmod=(+|-)x] [--pathspec-from-file=0 Bây giờ, chúng ta không thể chỉ thêm tất cả các đối số từ các mô hình khác nhau khi khởi động, vì chúng có các tên xung đột ( — num_layers) sẽ khiến trình phân tích cú pháp gặp sự cố. Trong tập tin trùng lặp. py, chúng tôi sao chép mã hoạt động trong phần trước và thêm các đối số từ hai mô hình, bạn có thể tìm thấy tại https. //github. com/mattiadg/example-cli/blob/main/src/duplicate_arguments. py $ git add --helpSYNOPSISgit add [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p] [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]] [--sparse] [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [-renormalize] [--chmod=(+|-)x] [--pathspec-from-file=1 Nếu bây giờ chúng ta chạy $ git add --helpSYNOPSISgit add [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p] [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]] [--sparse] [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [-renormalize] [--chmod=(+|-)x] [--pathspec-from-file=2 Chúng tôi nhận được lỗi dự kiến $ git add --helpSYNOPSISgit add [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p] [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]] [--sparse] [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [-renormalize] [--chmod=(+|-)x] [--pathspec-from-file=3 Rõ ràng là chúng ta cần một cách để thêm các đối số vào trình phân tích cú pháp của mình một cách linh hoạt, nghĩa là, trong thời gian chạy theo đầu vào từ người dùng của chúng ta. Tuy nhiên, không có phương thức nào của ArgumentParser cho phép chúng tôi thực hiện trực tiếp và chúng tôi cần sử dụng một mẹo nhỏ Chúng ta cần phân tích cú pháp các đối số hai lần, lần đầu tiên để lấy giá trị mô hình, sau đó tải các đối số tương ứng và sau đó với lần phân tích cú pháp thứ hai, chúng ta có thể nhận được các đối số dành riêng cho lệnh Để làm điều này, chúng ta cần trình phân tích cú pháp bỏ qua các đối số do người dùng chèn vào mà chưa được thêm làm đối số. May mắn thay, parse_known_args() thực hiện chính xác điều này $ git add --helpSYNOPSISgit add [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p] [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]] [--sparse] [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [-renormalize] [--chmod=(+|-)x] [--pathspec-from-file=4 trong đó parser_train là trình phân tích cú pháp con cho lệnh train, như trước đây và công cụ thay đổi trò chơi là dòng này $ git add --helpSYNOPSISgit add [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p] [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]] [--sparse] [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [-renormalize] [--chmod=(+|-)x] [--pathspec-from-file=5 cần nhận hai giá trị trả về vì parse_known_args trả về Tuple chứa các đối số được phân tích cú pháp ở vị trí đầu tiên và tất cả phần còn lại ở vị trí thứ hai dưới dạng danh sách. Đây là những gì chúng tôi nhận được bằng cách in kết quả của trình phân tích cú pháp. parse_known_args() $ git add --helpSYNOPSISgit add [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p] [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]] [--sparse] [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [-renormalize] [--chmod=(+|-)x] [--pathspec-from-file=6 Với sửa đổi mới nhất, cuối cùng chúng tôi cũng nhận được kết quả như mong đợi $ git add --helpSYNOPSISgit add [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p] [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]] [--sparse] [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [-renormalize] [--chmod=(+|-)x] [--pathspec-from-file=7 Và bước còn thiếu chỉ là hàm load_model_args() tải các đối số cho mô hình chính xác. Đây rồi $ git add --helpSYNOPSISgit add [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p] [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]] [--sparse] [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [-renormalize] [--chmod=(+|-)x] [--pathspec-from-file=8 Đây là một triển khai cơ bản, chỉ lấy tên mô hình, nhập mô-đun có cùng tên bên trong gói “mô hình”, sau đó gọi hàm add_arguments trong đó (hiển thị ở trên) trên trình phân tích cú pháp mà nó nhận làm đầu vào Điều còn thiếu ở đây là danh sách các mẫu có sẵn. Nếu được đặt một tên mô hình ngẫu nhiên, mã của chúng tôi sẽ bị lỗi vì không thể tìm thấy mô-đun tương ứng. Một cách khác là thêm vào sổ đăng ký trước tất cả các hàm add_arguments() từ tất cả các mô hình có tên tương ứng. Sau đó, chúng tôi có thể cung cấp các tùy chọn này dưới dạng “lựa chọn” trong đối số — mô hình. Điều này có thể dễ dàng thực hiện bằng cách sử dụng mẫu Đăng ký mà tôi đã mô tả trong bài viết trước Đa hình Python với thanh ghi. Mẫu PythonTìm hiểu một mẫu để cô lập các gói trong khi mở rộng các chức năng của mã Python của bạnhướng tới khoa học dữ liệu. com Tại sao chúng ta sử dụng mẫu này dường như làm tăng thêm độ phức tạp cho mã? . Sau đó, mã trở nên phức tạp vốn có và tốt hơn là tách biệt các thay đổi bằng cách có một điểm nhập duy nhất (đăng ký) cho từng danh mục và chỉ tạo giao diện mã cụ thể với mã chung. Ngoài ra, chức năng chính sẽ chỉ giao tiếp với mã di truyền (load_model args, trình tối ưu hóa tải args, v.v.) và cơ sở mã trở nên dễ suy luận hơn về Sự kết luậnTrong bài viết này, chúng ta đã thấy cách xây dựng clis có độ phức tạp tăng dần bằng cách sử dụng argparse từ thư viện chuẩn Python. Chúng tôi đã bắt đầu bằng cách đơn giản là sử dụng các trình phân tích con để thêm các lệnh phụ vào chương trình của mình, sau đó chúng tôi đã xem cách sử dụng parse_know_args để tải các đối số mới sau đó theo lựa chọn của người dùng. Cuối cùng, chúng tôi đã thảo luận về cách mẫu Đăng ký có thể giúp đạt được sự cô lập các mối quan tâm đối với trình phân tích cú pháp của chúng tôi Như một nhận xét mới nhất, nếu bạn quan tâm đến việc phát triển các công cụ cli, hãy cân nhắc sử dụng các thư viện cung cấp nhiều tính năng hơn argparse, chẳng hạn như cloup Tư cách thành viên trung bìnhBạn có thích bài viết của tôi và đang xem xét đăng ký Tư cách thành viên trung bình để có quyền truy cập không giới hạn vào các bài viết không? Nếu bạn quyết định đăng ký thông qua liên kết này, bạn sẽ hỗ trợ tôi thông qua đăng ký của bạn mà không phải trả thêm phí cho bạn https. //vừa phải. com/@mattiadigangi/thành viên |