2017-12-29 55 views
2

yaml을 덤핑 할 때 키 - 값에 들여 쓰기를 유지하는 방법은 무엇입니까? 나는 ruamel의 YAML을 사용하고yaml을 덤핑 할 때 키 - 값에서 들여 쓰기를 유지하는 방법

코드 :

in_str='''Pets: 
    Cat: 
     Tom 
    Mouse: 
     Jerry 
    Dog: 
     Scooby 
     ''' 


import ruamel.yaml, sys 
results = ruamel.yaml.load(in_str, ruamel.yaml.RoundTripLoader, preserve_quotes=True) 
results['Pets']['Bird']='Tweety' 
ruamel.yaml.dump(results, sys.stdout, ruamel.yaml.RoundTripDumper, default_flow_style=True,indent=2, block_seq_indent=2) 

출력 :

Pets: 
    Cat: Tom 
    Mouse: Jerry 
    Dog: Scooby 
    Bird: Tweety 

예상 출력 :

이를 달성하기 위해
Pets: 
    Cat: 
     Tom 
    Mouse: 
     Jerry 
    Dog: 
     Scooby 
    Bird: 
     Tweety 
+1

왜 들여 쓰기를 유지 하시겠습니까? –

+1

오래된 핸드가 설정을 유지합니다. 전체 파일을 포맷하면'git blame'의 느슨한 이점이 생깁니 까 –

+0

설정 파일에 시퀀스가 ​​없습니까? 이 방법으로 일관되게 들여 쓰는 중첩 된 매핑 만있는 경우 (다음 줄에 키보다 4 위치가 더 많음)이 작업을 수행 할 수 있어야합니다. BTW는 RoundTripDumper를 사용하여'default_flow_style = True'에 대한 필요성을 경감합니다. '들여 쓰기 '는 예상 출력에 더 가깝게하기 위해 4가되어야합니다; 'block_seq_indent'는 시퀀스에만 영향을줍니다. – Anthon

답변

2

당신이에 후크해야합니다 Emitter을 사용하고 매핑 값을 처리 할 때 줄 바꿈과 적절한 들여 쓰기를 삽입해야합니다. 사용중인 이전 스타일 API로 수행 할 수 있지만 새로운 ruamel.yaml API를 사용하면 더 효과적입니다. 다른 값으로 들여 쓰기 순서 및 매핑 가능성이 :

import sys 
import ruamel.yaml 
from ruamel.yaml.emitter import Emitter 

class MyEmitter(Emitter): 
    def expect_block_mapping_simple_value(self): 
     # type:() -> None 
     if getattr(self.event, 'style', None) != '?': 
      # prefix = u'' 
      if self.indent == 0 and self.top_level_colon_align is not None: 
       # write non-prefixed colon 
       c = u' ' * (self.top_level_colon_align - self.column) + self.colon 
      else: 
       c = self.prefixed_colon 
      self.write_indicator(c, False) 
      # the next four lines force a line break and proper indent of the value 
      self.write_line_break() 
      self.indent += self.best_map_indent 
      self.write_indent() 
      self.indent -= self.best_map_indent 
     self.states.append(self.expect_block_mapping_key) 
     self.expect_node(mapping=True) 


in_str='''\ 
Pets: 
    Cat: 
     Tom 
    Mouse: 
     - Jerry 
     - 'Mickey' 
    Dog: 
     Scooby 
     ''' 

yaml = ruamel.yaml.YAML() 
yaml.Emitter = MyEmitter 
yaml.indent(mapping=4, sequence=2, offset=0) 
yaml.preserve_quotes = True 
results = yaml.load(in_str) 
results['Pets']['Bird']='Tweety' 
yaml.dump(results, sys.stdout) 

이 제공 :

Pets: 
    Cat: 
     Tom 
    Mouse: 
     - Jerry 
     - 'Mickey' 
    Dog: 
     Scooby 
    Bird: 
     Tweety 

유의할 것들 :

  • 는 만 반대 (단순 스칼라 값을 처리해야 이미 블록 시퀀스 "모드"에서 다음 라인으로 "밀어 넣기"된 매핑/시퀀스)
  • expect_block_mapping_simple_value은 전자 원본 및 몇 줄을 추가했습니다. 현재 일부 코드를 복제하지 않으면이 작업을 수행 할 "후크"가 없습니다.
  • 시퀀스가 ​​있고 다른 들여 쓰기가 필요한 경우 sequenceoffset 값을 yaml.indent()으로 재생할 수 있습니다.
  • 이 모든 것은 일관된 들여 쓰기를 가정하고 개별 들여 쓰기가 유지되지 않습니다. 즉, 일부 값이 네 위치보다 많거나 적게 들여 쓰기되면 4 가지 위치로 끝납니다.