Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pyyaml and using quotes for strings only

I have the following YAML file:

---
my_vars:
  my_env: "dev"
  my_count: 3

When I read it with PyYAML and dump it again, I get the following output:

---
my_vars:
  my_env: dev
  my_count: 3

The code in question:

with open(env_file) as f:
    env_dict = yaml.load(f)
    print(yaml.dump(env_dict, indent=4, default_flow_style=False, explicit_start=True))

I tried using the default_style parameter:

with open(env_file) as f:
    env_dict = yaml.load(f)
    print(yaml.dump(env_dict, indent=4, default_flow_style=False, explicit_start=True, default_style='"'))

But now I get:

---
"my_vars":
  "my_env": "dev"
  "my_count": !!int "3"

What do I need to do to keep the original formatting, without making any assumptions about the variable names in the YAML file?

like image 773
Jeroen Jacobs Avatar asked Jul 14 '16 08:07

Jeroen Jacobs


People also ask

Does YAML need quotes around strings?

In general, you don't need quotes. Use quotes to force a string, e.g. if your key or value is 10 but you want it to return a String and not a Fixnum, write '10' or "10" . Use quotes if your value includes special characters, (e.g. : , { , } , [ , ] , , , & , * , # , ? , | , - , < , > , = , ! , % , @ , \ ).

Can YAML have single quotes?

In YAML, strings can be represented in the following several ways: Single-quoted scalars. Double-quoted scalars.

Do strings need quotation marks Python?

Python strings are sequences of characters and numbers. A string is wrapped around a set of single quotes or double quotes. There is no difference in which you use. Anything that goes inside the quotes is interpreted as being “text” instead an executable command.

How do you print a string with a quote in Python?

Use the escape character to print single and double quotes Use the escape character \ before double or single quotes to include them in the string.


1 Answers

I suggest you update to using YAML 1.2 (released in 2009) with the backwards compatible ruamel.yaml package instead of using PyYAML which implements most of YAML 1.1 (2005). (Disclaimer: I am the author of that package).

Then you just specify preserve_quotes=True when loading for round-tripping the YAML file:

import sys
import ruamel.yaml

yaml_str = """\
---
my_vars:
  my_env: "dev"    # keep "dev" quoted
  my_count: 3
"""

data = ruamel.yaml.round_trip_load(yaml_str, preserve_quotes=True)
ruamel.yaml.round_trip_dump(data, sys.stdout, explicit_start=True)

which outputs (including the preserved comment):

---
my_vars:
  my_env: "dev"    # keep "dev" quoted
  my_count: 3

After loading the string scalars will be a subclass of string, to be able to accommodate the quoting info, but will work like a normal string for all other purposes. If you want to replace such a string though (dev to fgw) you have to cast the string to this subclass ( DoubleQuotedScalarString from ruamel.yaml.scalarstring).

When round-tripping ruamel.yaml by default preserves the order (by insertion) of the keys.

like image 167
Anthon Avatar answered Oct 18 '22 07:10

Anthon