问题
Here is the Python code I've got:
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)
What I keep getting:
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
How do I change it to produce:
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
In other words I want to:
Avoid quotation marks and escape characters in the output so non-technical users can read and edit those config files.
Ideally preserve the order of parameters.
This is to be able to load a YAML file, add more parameters and still be able to save it in a human-friendly format.
回答1:
Your output has no newlines in the value for Pagargaph
, for that you would need to have a block-style literal scalar (the dash trims the final newline, you would normally get when loading such a scalar):
Pagargaph: |-
Lorem ipsum dolor sit amet,
consectetur adipiscing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
You should use ruamel.yaml (disclaimer: I am the author of that package), which is specifically developed to support this kind of round-tripping. To get what you want do e.g.:
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)
resulting in:
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
Please note:
- the order is preserved in any version of Python supported by ruamel.yaml (2.7, 3.4+)
- the comment is preserved
- the quotes that I added around
bbb
are preserved only if you specifyyaml.preserve_quotes = True
- since we insert twice at position 2, the latter bumps the former to position 3.
Your users will have to be a bit disciplined for them to be able to edit a YAML file and not break it. They should also know some of the caveats, such as that plain (non-quoted) scalars, cannot start with some special characters or contain special character sequences (:
followed by space, #
preceded by space)
To help prevent your users from making editing mistakes, you can try to add the following comment at the beginning of the YAML document:
# please read the first few "rules" of How_to_edit at the bottom of this file
and at the end:
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.
If you include the above, you probably don't want to preserve quotes when round-tripping.
来源:https://stackoverflow.com/questions/51187751/how-to-make-python-yaml-library-save-in-a-human-friendly-way