2012-02-06 31 views
7

Tiêu đề khá tự giải thích.Làm thế nào tôi có thể thêm một tuple python vào một tệp YAML bằng pyYAML?

Khi tôi tiết kiệm một tuple vào một tập tin YAML, tôi nhận được cái gì đó trông như thế này:

ambient: !!python/tuple [0.3, 0.3 ,0.3] 

Khi tôi cố gắng để tải nó với yaml.safe_load (file_object), tôi tiếp tục nhận được một lỗi mà đọc :

yaml.constructor.ConstructorError: could not determine a constructor for the tag 'tag:yaml.org,2002:python/tuple' 

Cần phải làm gì?

Trả lời

9

Trong pyyaml, Trình tải an toàn không bao gồm trình tải cho các kiểu gốc của python, chỉ các loại được xác định trong thông số yaml. Bạn có thể xem các loại cho số SafeLoaderLoader ở đây trong mẫu tương tác bên dưới.

Bạn có thể định nghĩa một lớp Loader mới biết thêm rằng trong các tuple trăn, nhưng không phải loại khác, vì vậy nó vẫn nên được khá an toàn:

import yaml 

class PrettySafeLoader(yaml.SafeLoader): 
    def construct_python_tuple(self, node): 
     return tuple(self.construct_sequence(node)) 

PrettySafeLoader.add_constructor(
    u'tag:yaml.org,2002:python/tuple', 
    PrettySafeLoader.construct_python_tuple) 

doc = yaml.dump(tuple("foo bar baaz".split())) 
print repr(doc) 
thing = yaml.load(doc, Loader=PrettySafeLoader) 
print thing 

kết quả là:

'!!python/tuple [foo, bar, baaz]\n' 
('foo', 'bar', 'baaz') 

Xem dưới đây cho các nhà xây dựng được liên kết với lớp SafeLoader và Loader.

>>> yaml.SafeLoader.yaml_constructors 
{None: <unbound method SafeConstructor.construct_undefined>, 
u'tag:yaml.org,2002:binary': <unbound method SafeConstructor.construct_yaml_binary>, 
u'tag:yaml.org,2002:bool': <unbound method SafeConstructor.construct_yaml_bool>, 
u'tag:yaml.org,2002:float': <unbound method SafeConstructor.construct_yaml_float>, 
u'tag:yaml.org,2002:int': <unbound method SafeConstructor.construct_yaml_int>, 
u'tag:yaml.org,2002:map': <unbound method SafeConstructor.construct_yaml_map>, 
u'tag:yaml.org,2002:null': <unbound method SafeConstructor.construct_yaml_null>, 
u'tag:yaml.org,2002:omap': <unbound method SafeConstructor.construct_yaml_omap>, 
u'tag:yaml.org,2002:pairs': <unbound method SafeConstructor.construct_yaml_pairs>, 
u'tag:yaml.org,2002:seq': <unbound method SafeConstructor.construct_yaml_seq>, 
u'tag:yaml.org,2002:set': <unbound method SafeConstructor.construct_yaml_set>, 
u'tag:yaml.org,2002:str': <unbound method SafeConstructor.construct_yaml_str>, 
u'tag:yaml.org,2002:timestamp': <unbound method SafeConstructor.construct_yaml_timestamp>} 

>>> yaml.Loader.yaml_constructors 
{None: <unbound method SafeConstructor.construct_undefined>, 
u'tag:yaml.org,2002:binary': <unbound method SafeConstructor.construct_yaml_binary>, 
u'tag:yaml.org,2002:bool': <unbound method SafeConstructor.construct_yaml_bool>, 
u'tag:yaml.org,2002:float': <unbound method SafeConstructor.construct_yaml_float>, 
u'tag:yaml.org,2002:int': <unbound method SafeConstructor.construct_yaml_int>, 
u'tag:yaml.org,2002:map': <unbound method SafeConstructor.construct_yaml_map>, 
u'tag:yaml.org,2002:null': <unbound method SafeConstructor.construct_yaml_null>, 
u'tag:yaml.org,2002:omap': <unbound method SafeConstructor.construct_yaml_omap>, 
u'tag:yaml.org,2002:pairs': <unbound method SafeConstructor.construct_yaml_pairs>, 
u'tag:yaml.org,2002:python/bool': <unbound method Constructor.construct_yaml_bool>, 
u'tag:yaml.org,2002:python/complex': <unbound method Constructor.construct_python_complex>, 
u'tag:yaml.org,2002:python/dict': <unbound method Constructor.construct_yaml_map>, 
u'tag:yaml.org,2002:python/float': <unbound method Constructor.construct_yaml_float>, 
u'tag:yaml.org,2002:python/int': <unbound method Constructor.construct_yaml_int>, 
u'tag:yaml.org,2002:python/list': <unbound method Constructor.construct_yaml_seq>, 
u'tag:yaml.org,2002:python/long': <unbound method Constructor.construct_python_long>, 
u'tag:yaml.org,2002:python/none': <unbound method Constructor.construct_yaml_null>, 
u'tag:yaml.org,2002:python/str': <unbound method Constructor.construct_python_str>, 
u'tag:yaml.org,2002:python/tuple': <unbound method Constructor.construct_python_tuple>, 
u'tag:yaml.org,2002:python/unicode': <unbound method Constructor.construct_python_unicode>, 
u'tag:yaml.org,2002:seq': <unbound method SafeConstructor.construct_yaml_seq>, 
u'tag:yaml.org,2002:set': <unbound method SafeConstructor.construct_yaml_set>, 
u'tag:yaml.org,2002:str': <unbound method SafeConstructor.construct_yaml_str>, 
u'tag:yaml.org,2002:timestamp': <unbound method SafeConstructor.construct_yaml_timestamp>} 
+0

Điều đó có ý nghĩa hoàn hảo. Cảm ơn nhiều! – blz

0

Ít nhất theo the PyYAML documentation:

giới hạn yaml.safe_load

Chức năng này khả năng các đối tượng Python đơn giản như số nguyên hoặc danh sách.

Danh sách, as you can see in the source, có phần mở rộng hơn nhưng không bao gồm tag:yaml.org,2002:python/tuple.

Dường như nếu bạn đang tạo loại !!python/tuple trong tệp YAML, bạn đang sử dụng dump() thay vì safe_dump(). Nếu trường hợp đó xảy ra, có thể bạn nên chuyển sang sử dụng load() thay cho safe_load() vì các tệp được tạo bởi dump() không được đảm bảo có thể tải bằng safe_load(). (Xem số description of safe_dump()).

+1

Tôi đã thêm từ bị thiếu * not *, nhưng tôi không chắc liệu bạn có thực sự không muốn xây dựng nó theo cách khác ... –

+0

@NiklasB .: Cảm ơn. – ig0774

+0

Trong điều kiện nào một người hợp lý xem xét việc sử dụng yaml.loader (trái ngược với safe_loader) có nguy hiểm không? Tôi đang viết một trò chơi tải các tài sản được định nghĩa trong một tệp YAML. Một bản tải xuống độc hại có thể được ghi đè lên các tệp YAML của tôi, do đó việc tải trò chơi của tôi là mã nguy hiểm, nhưng điều đó dường như là vấn đề của người dùng cuối. Tôi không thể làm gì nhiều ... đúng không? – blz

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