2015-02-17 13 views
10

Tôi có tệp some.yaml có nội dung bên dưới.Cách cập nhật tệp yaml bằng python

init_config: {} 
    instances: 
     - host: <IP> 
      username: <username> 
      password: <password> 

Tệp yaml phải được phân tích cú pháp và cập nhật như bên dưới.

init_config: {} 
    instances: 
     - host: 1.2.3.4 
      username: Username 
      password: Password 

Làm cách nào để phân tích các giá trị và cập nhật chúng một cách thích hợp?

+0

Nếu bạn sử dụng [PyYaml] (http://pyyaml.org/wiki/PyYAMLDocumentation), bạn có thể sử dụng Loader để load d ata và Dumper để ghi dữ liệu vào tệp. Dữ liệu được tải là một từ điển thông thường trong Python, do đó bạn có thể truy cập phần tử bằng khóa và do đó thay đổi nó theo ý muốn. –

+0

Không rõ nếu bạn muốn một công cụ mẫu (và đang chuyển hướng các câu trả lời hữu ích bằng cách quá hẹp) hoặc chỉ đơn giản là muốn phân tích cú pháp YAML và thay thế một số giá trị chuỗi trên dữ liệu được phân tích cú pháp. Cụ thể hơn và giải thích những gì bạn cần đạt được và tại sao. – MariusSiuram

+0

Đây là một tập tin. Tôi cần phân tích cú pháp tệp yaml và thay thế nội dung. – Chetan

Trả lời

14

Gói ruamel.yaml được tăng cường đặc biệt (bởi tôi bắt đầu từ PyYAML)) để thực hiện loại chuyến đi khứ hồi, có lập trình, cập nhật này.

Nếu bạn bắt đầu với (xin lưu ý tôi loại bỏ các không gian ban đầu thêm):

init_config: {} 
instances: 
    - host: <IP>    # update with IP 
     username: <username> # update with user name 
     password: <password> # update with password 

và chạy:

import ruamel.yaml 

file_name = 'input.yml' 
from ruamel.yaml.util import load_yaml_guess_indent 

config, ind, bsi = load_yaml_guess_indent(open(file_name)) 

instances = config['instances'] 
instances[0]['host'] = '1.2.3.4' 
instances[0]['username'] = 'Username' 
instances[0]['password'] = 'Password' 

ruamel.yaml.round_trip_dump(config, open('output.yml', 'w'), 
          indent=ind, block_seq_indent=bsi) 

Kết quả sẽ là:

init_config: {} 
instances: 
    - host: 1.2.3.4   # update with IP 
     username: Username  # update with user name 
     password: Password  # update with password 

Trật tự các phím ánh xạ (host, usernamepassword), kiểu và các ý kiến ​​ được bảo quản mà không có bất kỳ hành động cụ thể nào khác.

Thay vì có sự thụt lề và chuỗi khối thụt đoán, bạn có thể làm một tải truyền thống hơn , và thiết lập các indent giá trị bản thân:

config = ruamel.yaml.load(open(file_name), ruamel.yaml.RoundTripLoader) 
ind = 6 
bsi = 4 
0

Đây là mẫu sử dụng PyYaml. Theo tôi hiểu bạn có mẫu như định dạng yaml và bạn phải thay thế các vị trí trong dấu ngoặc nhọn bằng các giá trị thực.

import yaml 

s = """ 
    init_config: {} 
    instances: 
     - host: <IP> 
      username: <username> 
      password: <password> 
""" 

dict_obj = yaml.load(s) # loads string in internal data structure - dict 
dict_obj['instances'][0]['host'] = 'localhost' # change values 
print yaml.dump(dict_obj) # dumps dict to yaml format back 
+0

Một tệp đã có và tôi cần phải phân tích cú pháp và cập nhật nó. – Chetan

5

Đây là cách tôi có thể đọc từ tệp trên tôi đã đề cập, phân tích cú pháp và cập nhật khi cần.

import yaml 

fname = "some.yaml" 

stream = open(fname, 'r') 
data = yaml.load(stream) 

data['instances'][0]['host'] = '1.2.3.4' 
data['instances'][0]['username'] = 'Username' 
data['instances'][0]['password'] = 'Password' 

with open(fname, 'w') as yaml_file: 
    yaml_file.write(yaml.dump(data, default_flow_style=False)) 
+0

Có lẽ bạn nên đề cập rằng điều này ngăn không gian hàng đầu và không được bảo đảm để bảo vệ thứ tự của các phím ánh xạ (khi tôi chạy nó, tôi có 'host',' password', 'username' thay vì' host', 'username ',' mật khẩu '). – Anthon

3

Tôi không biết bạn có cần YAML hay không. Ngoài việc sử dụng thẻ YAML, có vẻ như bạn không có hứng thú với tài liệu YAML. Vậy tại sao không sử dụng Jinja2 hoặc một số ngôn ngữ mẫu?

from jinja2 import Template 

tmpl = Template(u'''\ 
    init_config: {} 
    instances: 
     - host: {{ IP }} 
      username: {{ username }} 
      password: {{ password }} 
''') 

print tmpl.render(
    IP=u"1.2.3.4", 
    username=u"Username", 
    password=u"Password" 
) 

Tôi không biết nếu nó là một ý tưởng tốt, nhưng nếu bạn chỉ cần để có được một tập tin với một số lĩnh vực thay đổi, bạn không cần phải thực sự phân tích các tài liệu YAML và có thể được hưởng lợi từ một Template ngôn ngữ trực tiếp.


Bonus: Sử dụng trường hợp

Tôi đã làm việc với các tài liệu YAML rất phức tạp, trong đó có thẻ chưa biết

... 
    propertiesIDs: { 1, 2, 3, 4 } 
    globalID: !myapplication.InterfaceID &primitiveID 

replication: !myapplication.replication 
    beginDate: 2012-09-10T20:00:03 
    endDate: 2020-09-10T20:00:04 
    replicant_uuid: 
    ? 17169504-B6AB-11E4-8437-36E258BB2172 
    ? 206B5842-B6AB-11E4-AAC3-36E258BB2172 
... 

Thực hiện phân tích cú pháp hợp lệ của tài liệu này là khó khăn và thời gian -trọng lượng. Tôi chỉ cần điền một số giá trị, và YAML được gửi đến một ứng dụng của bên thứ ba. Vì vậy, thay vì phân tích cú pháp YAML hoặc cố gắng tạo một tài liệu hợp lệ trực tiếp bằng pyyaml, thì đơn giản hơn (hiệu quả thời gian hơn, ít bị lỗi) để tạo nó trực tiếp thông qua các khuôn mẫu. Hơn nữa, các ngôn ngữ mẫu có thể dễ dàng được sử dụng với các vòng để điền các trường có kích thước động.

1

Dưới đây là làm thế nào tôi tạo mẫu Docker-cẩu cho dev, sản xuất , sân khấu, vv ...

  1. mkdir crane_templates
  2. lạc crane_templates/init py
  3. 01.
  4. Thêm mẫu nội dung với crane_templates nano/some.yaml
  5. Nano crane_gen.py

--- crane_gen.py ---

#!/usr/bin/env python 
from jinja2 import Environment, PackageLoader 

env = Environment(loader=PackageLoader('crane_templates', './')) 
tmpl = env.get_template('crane.yaml.tmpl') 

result = tmpl.render(
    IP=u"1.2.3.4", 
    username=u"Username", 
    password=u"Password" 
) 

5. python crane_gen.py> kết quả. yaml

trả lời lấy cảm hứng từ @MariusSiuram

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