2016-05-18 26 views
7

Tôi đang sử dụng argprase để tạo tùy chọn và đó là một tùy chọn rất cụ thể để thực hiện một công việc cụ thể. Tập lệnh hiện có khoảng 30 nút bấm và hầu hết không được sử dụng thường xuyên.Hiển thị tùy chọn ẩn bằng cách sử dụng argparse

tôi là tạo ra một tùy chọn:

opt.add_argument('-opt',help="Some Help", help=argparse.SUPPRESS) 

Nhưng tôi muốn có được hai cách thể hiện sự giúp đỡ cho các kịch bản:

my_script -help 
my_script -help-long 

Tôi muốn -help kéo dài đến cũng hiển thị tất cả các args ẩn. Tôi không thể tìm ra cách để làm điều này.

Có cách nào để thực hiện hành vi này không?

+1

Tôi không nghĩ điều đó là có thể, vì bạn ghi đè trợ giúp thuộc tính bằng 'argparse.SUPPRESS' thực sự là một chuỗi:' '== SUPPRESS ==' '. Bạn nhìn vào việc thực hiện 'add_argument', bạn có thể thấy rằng toàn bộ phương thức bị bỏ qua nếu' help == '== SUPPRESS ==' ' –

+0

Xin lỗi, đây là một chủ đề - tôi đã tự hỏi những nút bấm có ý nghĩa gì trong ngữ cảnh này - Tôi Googled cho knobs mã máy tính và không thấy bất cứ điều gì có liên quan. – PyNEwbie

+0

Nó chỉ là một từ đồng nghĩa cho tùy chọn. – chepner

Trả lời

8

Tôi không nghĩ rằng có một cách tích hợp để hỗ trợ việc này. Bạn có lẽ có thể hack xung quanh nó bằng cách kiểm tra sys.argv trực tiếp và sử dụng đó để sửa đổi cách bạn xây dựng các phân tích cú pháp:

import sys 
show_hidden_args = '--help-long' in sys.argv 

opt = argparse.ArgumentParser() 
opt.add_argument('--hidden-arg', help='...' if show_hidden_args else argparse.SUPPRESS) 
opt.add_argument('--help-long', help='Show all options.', action='help') 


args = opt.parse_args() 

Tất nhiên, nếu văn bản này hơn và hơn là quá bất tiện, bạn có thể bọc nó trong một hàm helper (hoặc lớp con ArgumentParser):

def add_hidden_argument(*args, **kwargs): 
    if not show_hidden_args: 
     kwargs['help'] = argparse.SUPPRESS 
    opt.add_argument(*args, **kwargs) 

Và có thể bạn sẽ muốn thêm một tổ chức phi ẩn --help-long lập luận để người dùng biết những gì nó cho là không ...

+0

Điều này hoạt động và có vẻ là giải pháp sạch nhất không sử dụng các tính năng không có giấy tờ –

1

bạn có thể đạt được một cái gì đó bởi subclassing ArgumentParser_HelpAction:

class LongHelp(argparse._HelpAction): 
    def __init__(self,*args, **kwargs): 
     super().__init__(*args, **kwargs) 

    def __call__(cls, parser, namespace, values, option_string): 
     print(parser.long_help) 

class ArgParserWithLongHelp(argparse.ArgumentParser): 
    def __init__(self): 
     super().__init__(self) 
     self.long_help = {} 
     self.add_argument("--long-help", action=LongHelp) 

    def add_argument(self, *args, **kwargs): 
     if kwargs.get('long_help'): 
      self.long_help.update({k:kwargs['long_help'] for k in args}) 
      kwargs.pop('long_help') 
     super().add_argument(*args, **kwargs) 

opt = ArgParserWithLongHelp() 
opt.add_argument('-opt', help=argparse.SUPPRESS, long_help='Some extra help') 
args = opt.parse_args() 
+0

Điều này không định dạng thông báo trợ giúp giống như argparse bình thường, vì vậy nó sẽ làm cho việc sử dụng này hơi kỳ quặc - Hoặc bạn cần lưu trữ dữ liệu trong định dạng có cấu trúc và làm tốt hơn một chút để định dạng thông báo trợ giúp theo cách hữu ích hơn (mà tôi không nghĩ là một nhiệm vụ tầm thường). – mgilson

+0

Vâng, đó chỉ là để thể hiện ý tưởng. Có thể sử dụng phương pháp định dạng _HelpAction. Giải pháp của bạn chắc chắn là thẳng tiến hơn. –

+0

Điều này hoạt động tốt hơn nếu bạn thêm thuộc tính bổ sung vào đối số: 'hidden'. Nếu được gọi với '--help', thì' _HelpAction' bỏ qua bất kỳ thứ gì là 'ẩn'. '--help-long' gọi cả hai. Bạn thậm chí có thể làm cho '--help-long' bị ẩn, nếu cần thiết. –

1

Đây là một biến thể của câu trả lời @ mgilson, nhìn trong sys.argv để xem liệu chúng ta nên ngăn chặn một số giúp đỡ hay không

import argparse 
import sys 

def hide_args(arglist): 
    for action in arglist: 
     action.help=argparse.SUPPRESS 

hidelist=[]  
parser = argparse.ArgumentParser() 
a1 = parser.add_argument('--foo',help='normal') 
a2 = parser.add_argument('--bar',help='hidden') 
hidelist.append(a2) 

if '-h' in sys.argv[1:]: 
    hide_args(hidelist) 
args = parser.parse_args() 

Ở đây tôi đã chọn để giải thích --help như yêu cầu để được giúp đỡ lâu dài; -h cho ngắn. Thay vào đó, tôi có thể đã thêm đối số --longhelp riêng biệt.

1207:~/mypy$ python3 stack37303960.py --help 
usage: stack37303960.py [-h] [--foo FOO] [--bar BAR] 

optional arguments: 
    -h, --help show this help message and exit 
    --foo FOO normal 
    --bar BAR hidden 

cho một trợ giúp ngắn

1207:~/mypy$ python3 stack37303960.py -h 
usage: stack37303960.py [-h] [--foo FOO] 

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

add_argument trả về một con trỏ đến đối tượng Action mà nó tạo ra. Ở đây tôi lưu những cái đã chọn trong số hidelist. Sau đó, tôi có điều kiện lặp qua danh sách đó và thay đổi help thành SUPPRESS. Nhiều thuộc tính của một hành động có thể được thay đổi sau khi tạo ban đầu (thử nghiệm trong một phiên tương tác).

Trình phân tích cú pháp cũng duy trì danh sách tác vụ. Mặc định help là chữ cái đầu tiên trên danh sách parser._actions. Nó sử dụng danh sách này để phân tích cú pháp và định dạng trợ giúp.

In [540]: parser._actions[0] 
Out[540]: _HelpAction(option_strings=['-h', '--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='show this help message and exit', metavar=None) 
+0

FWIW, bạn đang đề xuất sự phụ thuộc vào một loạt các tính năng argparse không có giấy tờ. Lần cuối cùng tôi kiểm tra, nó không được ghi lại rằng 'parser.add_argument' trả về _anything_. Với điều đó, argparse internals _seem_ khá ổn định, vì vậy rủi ro bạn đang dùng có lẽ không phải là _too_ lớn. – mgilson

+0

Tài liệu 'argparse' là một chút yếu trong loại điều đó. Nó có rất nhiều chi tiết hướng dẫn, nhưng không mô tả một cách hệ thống các lớp và cách chúng được tạo ra. Vì tôi làm hầu hết các thử nghiệm 'argparse' của tôi trong một phiên Ipython, nó trở thành bản chất thứ hai. Trong http://bugs.python.org/issue19462 Tôi đề xuất một số hành động tương tự cho một người áp phích muốn có phương thức 'remove_argument'. – hpaulj

+0

Tôi đã đề cập 2 năm trước trong một lỗi/vấn đề rằng sự trở lại của 'add_argument' không được ghi lại. http://bugs.python.org/msg225794. Nhưng có nhiều bản sửa lỗi hữu ích hơn trong hàng đợi. – hpaulj

Các vấn đề liên quan