2015-06-07 27 views
6
parser = argparse.ArgumentParser() 
parser.add_argument("-p", "--pattern", help="Pattern file") 
args = parser.parse_args() 

Bây giờ, bạn có thể lấy lại chuỗi "--pattern" từ args? Tôi cần chuỗi để tôi có thể xây dựng một danh sách cmd để chuyển đến Popen như Popen(['some_other_program', args.pattern.option_string, args.pattern], ...) mà không lặp lại nó (và phải duy trì nó ở hai nơi) (Popen(['some_other_prog', '--pattern', args.pattern], ...)).Làm thế nào để lấy lại chuỗi tùy chọn bằng cách sử dụng argparse?

Tôi cần tạo trình bao bọc cho chương trình khác. Một số các args cần phải được chuyển đến chương trình gói (thông qua Popen) và một số được yêu cầu bởi các wrapper.


Có phương pháp nào tốt hơn ví dụ sau không?

pass_1 = '--to-be-passed' 
parser = argparse.ArgumentParser() 
parser.add_argument("-p", pass_1, help="Pass me on") 
parser.add_argument("-k", "--arg-for-wrapper") 
args = parser.parse_args() 

... 
process = Popen(['wrapped_program', pass_1, args.pass_1], ...) 
... 

Phương pháp này giữ args trong các biến không phải là rất tốt như:

  1. Duy trì tùy chọn ngắn cùng với tùy chọn dài trở nên khó khăn.
  2. Popen nếu được gọi trong một chức năng khác yêu cầu chuyển các biến này (hoặc một mệnh đề của chúng) cho hàm. Điều này có vẻ dư thừa như args được chuyển cho nó là đủ.
+1

Tại sao bạn không chỉ cần lưu nó trong một biến? '' pattern_str = '--pattern''', rồi '' ..add_argument (... pattern_str ...) ''. Ở đó - chỉ có một điểm duy trì. –

+0

Có vẻ như bạn đang cố gắng mã hóa một sự phụ thuộc giữa hai chương trình riêng biệt (và không linh hoạt như vậy: "các chương trình này phải chia sẻ tên tùy chọn"). Đó có thực sự là điều bạn muốn làm không? – Hurkyl

+0

@Hurkyl Có, chương trình python là một trình bao bọc cho một chương trình khác. – user80551

Trả lời

2

Thêm dest vào cuộc gọi add_argument của bạn.

parser.add_argmument("p", "--pattern", dest="pattern", help="your help text") 
args = parser.parse_args() 
args = vars(args) 

Bạn có thể tham chiếu mẫu với args["pattern"].

+2

'argparse' suy ra rằng dest là' pattern' từ '--pattern'. Vì vậy, thêm 'dest' là không cần thiết. 'args' là một đối tượng Không gian tên, không phải là từ điển. 'vars (args)' tạo ra một từ điển từ nó. – hpaulj

1

Câu trả lời và nhận xét đã xóa cho biết có một số nhầm lẫn về những gì bạn muốn. Vì vậy, tôi sẽ thêm vào sự nhầm lẫn đó.

Thông thường trình phân tích cú pháp không ghi chuỗi tùy chọn. Tuy nhiên, nó được cung cấp cho phương thức Action__call__. Vì vậy, một lớp Action có thể lưu nó. Ví dụ về lớp tùy chỉnh FooAction trong tài liệu argparse minh họa điều này.

Nếu tôi xác định lớp con hành động này:

In [324]: class PassThru(argparse._StoreAction): 
def __call__(self, parser, namespace, values, option_string=None): 
    setattr(namespace, self.dest, [values, option_string]) 

In [324]: p.add_argument('-o','--other',action=PassThru) 

Chuỗi tùy chọn được ghi lại cùng với các giá trị ('-o' hoặc '--Góc'):

In [322]: p.parse_args('-p test -o teseting'.split()) 
Out[322]: Namespace(other=['teseting', '-o'], pass_me_on='test') 

In [323]: p.parse_args('-p test --other teseting'.split()) 
Out[323]: Namespace(other=['teseting', '--other'], pass_me_on='test') 

Rõ ràng là option_string và giá trị có thể được ghi theo thứ tự khác, trong từ điển, dưới dạng thuộc tính riêng biệt trong Không gian tên, v.v.


Có nhiều cách khác để chuyển các tùy chọn cho một chương trình khác, đặc biệt nếu trình phân tích cú pháp gói không cần xử lý chúng.

argparse lấy đối số từ sys.argv[1:] và không thay đổi đối số. Vì vậy, ngay cả khi trình phân tích cú pháp của bạn sử dụng một số đối số, bạn có thể chuyển danh sách đó vào popen (tất cả hoặc một phần).

Tài liệu argparse có một ví dụ, dưới nargs=REMAINDER, về phân tích cú pháp một số đối số cho chính nó và thu thập phần còn lại để chuyển sang chương trình khác.Đây là ví dụ của họ:

>>> parser = argparse.ArgumentParser(prog='PROG') 
>>> parser.add_argument('--foo') 
>>> parser.add_argument('command') 
>>> parser.add_argument('args', nargs=argparse.REMAINDER) 
>>> print(parser.parse_args('--foo B cmd --arg1 XX ZZ'.split())) 
Namespace(args=['--arg1', 'XX', 'ZZ'], command='cmd', foo='B') 

Vì vậy, bạn có thể gọi popen với một cái gì đó giống như

plist = ['wrapped_program'] 
plist.extend(args.args) 
popen(plist, ...) 

Sử dụng parse.parse_known_args cũng có thể được sử dụng để thu thập lời chưa phân tích thành một danh sách 'extras'. Phần đó của các tài liệu nói về việc truyền các chuỗi đó đến một chương trình khác (giống như bạn đang làm). Ngược lại với trường hợp REMAINDER, các công cụ bổ sung không nhất thiết phải là cuối cùng.

Những công việc này, tất nhiên, chỉ khi trình phân tích cú pháp này không cần --pattern cho chính nó. Nếu nó phân tích cú pháp, nó sẽ không xuất hiện trong REMAINDER hoặc phần bổ sung. Trong trường hợp đó bạn sẽ phải thêm nó trở lại danh sách mà bạn cung cấp popen

tôi sẽ tinh chỉnh phân tích cú pháp của bạn như sau:

pass_1 = 'passed' # without the -- or internal - 
dpass_` = '--'+pass_ 
parser = argparse.ArgumentParser() 
parser.add_argument("-p", dpass_1, help="Pass me on") 
parser.add_argument("-k", "--arg-for-wrapper") 
args = parser.parse_args() 
process = Popen(['wrapped_program', dpass_1, getattr(args, pass_1)], ...) 

tùy chọn khác:

parser = argparse.ArgumentParser() 
pass_action = parser.add_argument("-p", '--pass-me-on', help="Pass me on") 
parser.add_argument("-k", "--arg-for-wrapper") 
args = parser.parse_args() 

Nếu bạn in pass_action (trong một vỏ) bạn sẽ nhận được một cái gì đó như:

_StoreAction(option_strings=['-p', '--pass-me-on'], dest='pass_me_on', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None) 

Vì vậy, bạn c Ould kéo --namedest từ đối tượng đó, như sau:

process = Popen(['wrapped_program', pass_action.option_strings[-1], getattr(args, pass_action.dest), ...], ...) 

Bạn cần phải nhìn vào sys.argv để xem option_string đã được sử dụng (dài, ngắn hoặc khác). Trình phân tích cú pháp không ghi lại bất cứ đâu.

Lưu ý '--pass-me-on' được sản xuất dest='pass_me_on'. Việc chuyển đổi - thành _ có thể làm phức tạp phát sinh một chuỗi từ chuỗi kia.

Nếu bạn có chuỗi dest, bạn phải sử dụng getattr để kéo nó từ không gian tên args hoặc sử dụng vars(args)[dest] (truy cập từ điển).

Một vấn đề khác. Nếu --pattennargs='+', its value will be a list, as opposed to a string. You'd have to careful when merging that into the danh sách đối số popen`.

0

Có vẻ như không phải là cách dễ dàng để nhận các chuỗi tùy chọn gốc từ kết quả của parser.parse_args(), nhưng bạn có thể lấy chúng từ đối tượng parser. Bạn chỉ cần nhìn vào __dict__, để truy xuất cài đặt parser sau khi được tạo. Trong trường hợp của bạn, bạn muốn trường _option_string_actions. Thật không may, điều này dường như không được hỗ trợ chính thức, vì tôi không thể tìm thấy phương thức ArgumentParser dành riêng cho điều này, vì vậy YMMV. Mở Python 3:

Demo:

parser = argparse.ArgumentParser() 
parser.add_argument('--foo', '-f', type=int, default=1000, help='intensity of bar') 
parser.add_argument('--bar', '-b', type=str, default='bla', help='whatever') 
store_action_dict=vars(parser)['_option_string_actions'] 
print(store_action_dict.keys()) # dict_keys(['--help', '-b', '-f', '-h', '--foo', '--bar']) 
Các vấn đề liên quan