2013-09-04 114 views
20

Tôi đang cố gắng chấp nhận một đối số kiểu = dict với argparse nhưng không có vấn đề gì khi nó đưa ra một lỗi giá trị dict không hợp lệ.Chấp nhận một từ điển làm đối số với argparse và python

#!/usr/bin/env python 

import argparse 

MYDICT = {'key': 'value'} 

parser = argparse.ArgumentParser() 
parser.add_argument("-m", "--mydict", action="store", 
        required=False, type=dict, 
        default=MYDICT) 

args = parser.parse_args() 

print args.mydict 

Đây là những gì xảy ra khi tôi cố gắng và vượt qua một từ điển để kịch bản

./argp.py -m "{'key1': 'value1'}" 
usage: argp.py [-h] [-m MYDICT] 
argp.py: error: argument -m/--mydict: invalid dict value: "{'key1': 'value1'}" 

Nhìn vào tài liệu tôi sẽ nghĩ rằng điều này sẽ thực hiện được.

http://docs.python.org/dev/library/argparse.html

“Bất cứ đối tượng có hỗ trợ trong điều hành có thể được thông qua như giá trị lựa chọn, các đối tượng để dict, bộ đối tượng, container tùy chỉnh, vv đều được hỗ trợ.”

+0

Dòng bạn trích dẫn từ tài liệu liên quan đến đối số từ khóa "lựa chọn", xác định giá trị của các đối số được cho phép. Thông qua một dict để lựa chọn có hiệu quả tương đương với đi qua một danh sách các phím. Do đó, việc chuyển "{'a': 2, 'b': 3}" sẽ hạn chế các đối số được phép cho cờ "--mydict" thành "a" hoặc "b". –

Trả lời

26

Tôi không nghĩ có thể chuyển từ điển làm đối số trong dòng lệnh vì không tồn tại hàm chuyển đổi từ chuỗi thành dict (EDIT: Một hack có thể, xem bên dưới). Điều bạn chủ yếu nói với python là:

dict("{'key1': 'value1'}") 

Nếu bạn dùng thử trong bảng điều khiển python, không hoạt động.

gì cụm từ:

"Bất cứ đối tượng có hỗ trợ trong điều hành có thể được thông qua như giá trị lựa chọn, các đối tượng để dict, bộ đối tượng, container tùy chỉnh, vv đều được hỗ trợ."

đề cập đến là lựa chọn lập luận cho rằng có thể được thông qua với add_argument chức năng - không đến loại tranh cãi.

Đặt cược của bạn tốt nhất là có thể chấp nhận lập luận của mình như là một chuỗi và sau đó chuyển đổi nó bằng cách sử dụng khả năng của json python:

parser.add_argument('-m', '--my-dict', type=str) 
args = parser.parse_args() 

import json 
my_dictionary = json.loads(args.my_dict) 

Sau đó bạn có thể vượt qua một cuốn từ điển trong các hình thức của một chuỗi. Bạn có thể thử các json mã hóa/giải mã ra cho chính mình trong python console để xem làm thế nào nó hoạt động:

>>>json.loads('{"value1":"key1"}') 
{u'value1': u'key1'} 

EDIT: hpaulj đã chỉ ra cho tôi rằng bạn có thể "hack" các loại tham số bởi chuyển nó json.loads.

import json 
parser.add_argument('-d', '--my-dict', type=json.loads) 
args = parse.parse_args() 

mydict = args.my_dict # Will return a dictionary 

Lý do công việc này thực sự khá thú vị vì giá trị tham số bên trong sẽ chỉ sử dụng giá trị tham số làm hàm chuyển đổi đối số. tức là nếu type = int thì nó sẽ sử dụng int (arg) hoặc nếu type = json.loads rồi json.tải (arg)

Điều này cũng có nghĩa là bạn có thể chuyển bất kỳ hàm nào có tham số để nhập và thực hiện chuyển đổi tùy chỉnh nếu bạn cần :)

+20

'type = json.loads' hoạt động – hpaulj

+1

Điều đó thực sự có ý nghĩa rất nhiều vì như tôi đã đề cập ở trên, tham số được truyền cho kiểu được xử lý bằng cách đặt đối số trong dấu ngoặc đơn. Cảm ơn bạn đã chỉ ra điều đó. –

+0

Tôi không nhất thiết phải gọi đó là "hack". Nó thực sự là cách đối số kiểu được cho là hoạt động – mdw7326