Как сделать так, чтобы библиотека Python Yaml сохранялась в удобной для человека форме? - PullRequest
0 голосов
/ 05 июля 2018

Вот код Python, который я получил:

d = {'ToGoFirst': 'aaa', 'Second': 'bbb', 'Pagargaph':
'''Lorem ipsum dolor sit amet, 
consectetur adipiscing elit, 
sed do eiusmod tempor incididunt 
ut labore et dolore magna aliqua.''',  
'Integer': 25}
with open('d.yaml', 'w') as f:
    yaml.safe_dump(d, f, default_flow_style=False)

Что я продолжаю получать:

Integer: 25
Pagargaph: "Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit, \nsed do eiusmod\
  \ tempor incididunt \nut labore et dolore magna aliqua."
Second: bbb
ToGoFirst: aaa

Как мне изменить это, чтобы произвести:

ToGoFirst: aaa
Second: bbb
Pagargaph: 
  Lorem ipsum dolor sit amet, 
  consectetur adipiscing elit, 
  sed do eiusmod tempor incididunt 
  ut labore et dolore magna aliqua.
Integer: 25

Другими словами, я хочу:

  1. Избегайте кавычек и escape-символов в выходных данных, чтобы нетехнические пользователи могли читать и редактировать эти файлы конфигурации.

  2. Идеально сохранить порядок параметров.

Это позволяет загружать YAML-файл, добавлять дополнительные параметры и сохранять его в удобном для человека формате.

1 Ответ

0 голосов
/ 05 июля 2018

В вашем выводе нет новых строк в значении Pagargaph, для этого вам понадобится буквальный скаляр в стиле блока (тире обрезает последний символ новой строки, который вы обычно получаете при загрузке скаляр):

Pagargaph: |-
  Lorem ipsum dolor sit amet, 
  consectetur adipiscing elit, 
  sed do eiusmod tempor incididunt 
  ut labore et dolore magna aliqua.

Вы должны использовать ruamel.yaml (заявление об отказе: я являюсь автором этого пакета), который специально разработан для поддержки такого рода циклического отключения. Чтобы получить то, что вы хотите сделать, например:

import sys
import ruamel.yaml
from ruamel.yaml.scalarstring import PreservedScalarString as L

yaml_str = """\
ToGoFirst: aaa
Second: 'bbb'  # insert after this one
Integer: 25
"""

yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
d = yaml.load(yaml_str)
# yaml.indent(mapping=4, sequence=4, offset=2)
try:
    before_integer = [k for k in d].index('Integer')
except ValueError:
    before_integer = len(d)
d.insert(before_integer, 'Pagargaph', L('''Lorem ipsum dolor sit amet, 
consectetur adipiscing elit, 
sed do eiusmod tempor incididunt 
ut labore et dolore magna aliqua.'''))  
d.insert(before_integer, 'Something', 'extra', comment='with a comment')
yaml.dump(d, sys.stdout)

в результате:

ToGoFirst: aaa
Second: 'bbb'  # insert after this one
Something: extra # with a comment
Pagargaph: |-
  Lorem ipsum dolor sit amet, 
  consectetur adipiscing elit, 
  sed do eiusmod tempor incididunt 
  ut labore et dolore magna aliqua.
Integer: 25

Обратите внимание:

  • порядок сохраняется в любой версии Python, поддерживаемой ruamel.yaml (2.7, 3.4+)
  • комментарий сохраняется
  • цитаты, которые я добавил около bbb, сохраняются, только если вы укажете yaml.preserve_quotes = True
  • , так как мы вставляем дважды в позицию 2, последний переводит первый в позицию 3.

Ваши пользователи должны быть немного дисциплинированными, чтобы они могли редактировать YAML-файл, а не ломать его. Они также должны знать, что некоторые предостережения, такие как простые (не заключенные в кавычки) скаляры, не могут начинаться с некоторых специальных символов или содержать последовательности специальных символов (: с последующим пробелом, # с предшествующим пробелом)

Чтобы пользователи не допускали ошибок при редактировании, попробуйте добавить следующий комментарий в начале документа YAML:

# please read the first few "rules" of How_to_edit at the bottom of this file

и в конце:

How_to_edit: |
 Editing a YAML document is easy, but there are some rules to keep you from 
 accidently invoking its hidden powers. Of the following you need at least 
 read and apply the ones up to the divider separating the important from less 
 important rules. The less important ones are interesting, but you probably 
 won't need to know them.
 1) Entries in this file consist of a scalar key (before the ':') and a scalar 
    value (normally after the ':', but read rule 3). 
 2) Scalars do NOT need quotes (single: ', or double: ") around them, unless 
    you have a special character or characters combinations at the beginning 
    ('%', '*', '&', '{', '[', '- ') or in the middle  (': ', ' #) of the  scalar.
    If you add quotes use a single quote before and after the scalar . If 
    these are superfluous the program can remove them. So when in doubt just 
    add them.
 3) A key followed by ': |' introduces a multiline scalar. These instructions
    are in a multiline scalar. Such a scalar starts on the next line after ': |'.
    The lines need to be indented, until the end of the scalar and these 
    indentation spaces are not part of the scalar. 
    The newlines in a multiline sclar are hard (i.e. preserved, and not 
    substituted with spaces).
    If you see `: |-` that means the scalar is loaded with the trailing newline 
    stripped.
 4) Anything after a space followed by a hash (' #') is a comment, when not 
    within quotes or in a multiline string.
 --- end of the important rules ---
 5) Within single quoted scalars you can have a single quote by doubling it: 
       rule 4: 'you probably don''t ever need that'
    This is called escaping the single quote. You can double quote scalars, but 
    the rules for escaping are much more difficult, so don't try that at home.
 6) The scalars consisting solely of "True" and "False" (also all-caps and 
    all-lowercase) are loaded as booleans when unquoted, and as strings when 
    quoted. 
 7) Scalars consisting solely of number characters (0-9) are loaded as numbers.
    If there is a non-number they are usually loaded as strings, but scalars 
    starting with '0x' and '0o' and for the rest have only number characters,
    are special and need quotes if not intended as (hexadecimal resp. octal) 
    numbers.

Если вы включите вышеупомянутое, вы, вероятно, не хотите сохранять кавычки при циклическом отключении.

...