2012-11-22 35 views
13

Tôi đang tạo tài liệu Yaml từ các đối tượng python của riêng tôi bằng PyYaml. ví dụ đối tượng của tôi: Thêm nhận xét vào YAML được tạo bằng PyYaml

class MyObj(object): 
    name = "boby" 
    age = 34 

trở thành:

boby: 
    age: 34 

Cho đến nay rất tốt.

Nhưng tôi đã không tìm thấy một cách để lập trình thêm ý kiến ​​để các yaml sản xuất vì vậy nó sẽ trông giống như:

boby:  # this is the name 
    age: 34 # in years 

Nhìn vào tài liệu PyYaml và cũng vào mã, tôi thấy không có cách nào làm như vậy.

Mọi đề xuất?

+0

Tôi gần như chắc chắn không có cách nào để làm điều này với PyYAML ngắn về cơ bản viết lại các phần chính của thư viện và đưa ra một số quyết định về cách xử lý nhận xét. Bạn có muốn nhận xét do người gửi lại thêm (ví dụ: mỗi lớp) không? Hoặc mỗi trường hợp bằng cách nào đó (thậm chí khó khăn hơn)? Điều này có phần không may, vì khả năng thêm nhận xét có thể hơi hữu ích. – cge

+0

Cảm ơn @cge. Việc lưu giữ các chú thích sẽ rất hữu ích khi xử lý các tài liệu yaml theo chương trình. –

+0

http://www.dzone.com/snippets/pyyaml-comment-emitter dường như hiểu cách sử dụng giao diện Event/Dumper. Chưa đăng câu trả lời vì tôi chưa xác minh câu trả lời. – kampu

Trả lời

4

Bạn có thể có một số representer cho lớp myObj, như theo mặc định bán phá giá (print(yaml.dump(MyObj()))) với PyYAML sẽ cung cấp cho bạn:

!!python/object:__main__.MyObj {} 

PyYAML chỉ có thể làm một việc có ý kiến ​​trong đầu ra mong muốn của bạn: loại bỏ chúng . Nếu bạn muốn đọc mà đầu ra mong muốn trở lại, bạn kết thúc lên với một dict chứa một dict ({'boby': {'age': 34}}, bạn sẽ không nhận được một trường hợp MyObj() vì không có thông tin thẻ)

Các phiên bản nâng cao cho PyYAML mà tôi phát triển (ruamel.yaml) có thể đọc trong YAML với ý kiến, giữ lại các bình luận và viết bình luận khi bán phá giá. Nếu bạn đọc kết quả mong muốn của mình, dữ liệu kết quả sẽ trông (và hành động) giống như một dict chứa một dict, nhưng trong thực tế có cấu trúc dữ liệu phức tạp hơn có thể xử lý các nhận xét. Tuy nhiên, bạn có thể tạo cấu trúc đó khi ruamel.yaml yêu cầu bạn đổ một phiên bản MyObj và nếu bạn thêm nhận xét vào lúc đó, bạn sẽ nhận được kết quả mong muốn.

from __future__ import print_function 

import sys 
import ruamel.yaml 
from ruamel.yaml.comments import CommentedMap 


class MyObj(): 
    name = "boby" 
    age = 34 

    def convert_to_yaml_struct(self): 
     x = CommentedMap() 
     a = CommentedMap() 
     x[data.name] = a 
     x.yaml_add_eol_comment('this is the name', 'boby', 11) 
     a['age'] = data.age 
     a.yaml_add_eol_comment('in years', 'age', 11) 
     return x 

    @staticmethod 
    def yaml_representer(dumper, data, flow_style=False): 
     assert isinstance(dumper, ruamel.yaml.RoundTripDumper) 
     return dumper.represent_dict(data.convert_to_yaml_struct()) 


ruamel.yaml.RoundTripDumper.add_representer(MyObj, MyObj.yaml_representer) 

ruamel.yaml.round_trip_dump(MyObj(), sys.stdout) 

nào in:

boby:  # this is the name 
    age: 34 # in years 

Không cần phải chờ đợi với việc tạo ra các CommentedMap trường cho đến khi bạn muốn để đại diện cho các trường hợp MyObj. Tôi sẽ ví dụ tạo nameage thành các thuộc tính nhận/đặt các giá trị từ/trên số CommentedMap được phê duyệt. Bằng cách đó, bạn có thể dễ dàng thêm nhận xét trước khi phương thức tĩnh yaml_representer được gọi để đại diện cho phiên bản MyObj.

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