Я использую модуль yaml
в своем скрипте Python для создания файла YAML. Ниже приведен пример:
import yaml
class MyDumper(yaml.Dumper):
def increase_indent(self, flow=False, indentless=False):
return super(MyDumper, self).increase_indent(flow, False)
foo = {
'instance_type': 'test',
'hostname': "\"testhost\"",
'name': 'foo',
'my_list': [
{'foo': 'test', 'bar': 'test2'},
{'foo': 'test3', 'bar': 'test4'}],
'hello': 'world',
}
print yaml.dump(foo, Dumper=MyDumper, default_flow_style=False)
Выход:
hello: world
hostname: '"testhost"'
instance_type: test
my_list:
- bar: test2
foo: test
- bar: test4
foo: test3
name: foo
В приведенном выше выводе имя хоста имеет одинарные и двойные кавычки, я хочу только двойные кавычки.
Ожидаемый результат:
hello: world
hostname: "testhost"
instance_type: test
my_list:
- bar: test2
foo: test
- bar: test4
foo: test3
name: foo
Вы не можете форсировать котировки в YAML, цитируя части своих данных так же, как и вы. Поскольку цитаты заставляют самосвал применять цитирование к скаляру (т.е. Больше не могут использовать простые скаляры, как для других строковых значений в вашем файле yaml).
Вам нужно создать тип, который сбрасывается кавычками. Наиболее легко это делается с помощью ruamel.yaml
(отказ от ответственности: я являюсь автором этой расширенной версии PyYAML, поддерживающей YAML 1.2, поддерживает сохранение комментариев и цитат в обоих направлениях и т.д.).
import sys
import ruamel.yaml
from ruamel.yaml.scalarstring import DoubleQuotedScalarString as dq
yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)
foo = {
'instance_type': 'test',
'hostname': dq("testhost"),
'name': 'foo',
'my_list': [
{'foo': 'test', 'bar': 'test2'},
{'foo': 'test3', 'bar': 'test4'}],
'hello': 'world',
}
yaml.dump(foo, sys.stdout)
который дает:
instance_type: test
hostname: "testhost"
name: foo
my_list:
- foo: test
bar: test2
- foo: test3
bar: test4
hello: world
Вы также можете легко загрузить этот вывод и сбросить его, генерируя точно такой же вывод:
from ruamel.yaml.compat import StringIO
buf = StringIO()
yaml.dump(foo, buf)
yaml.preserve_quotes = True
data = yaml.load(buf.getvalue())
yaml.dump(data, sys.stdout)
Вы получаете двукратные кавычки, потому что это то, что ваши входные данные имеют. Эта строка:
'hostname': "\"testhost\"",
говорит, что вы хотите, чтобы hosthame
имел в качестве значения 10-символьную строку, начинающуюся и заканчивающуюся на "
, и это то, что вы видите в yaml. Эта строка с экранированными двойными кавычками "\"testhost\""
и версия yaml '"testhost"'
это два разных представления исходных кодов одинаковых данных. Вам нужно только удвоить кавычки вокруг строки в yaml, если вы хотите вставлять в нее специальные символы (например, \n
для новой строки). Но yaml.dump()
будет заботиться этого для вас.
Если вы настаиваете на том, чтобы делать это через PyYAML, вы можете объявить свой собственный тип принудительной котировки и добавить своего представителя:
import yaml
class MyDumper(yaml.Dumper): # your force-indent dumper
def increase_indent(self, flow=False, indentless=False):
return super(MyDumper, self).increase_indent(flow, False)
class QuotedString(str): # just subclass the built-in str
pass
def quoted_scalar(dumper, data): # a representer to force quotations on scalars
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='"')
# add the QuotedString custom type with a forced quotation representer to your dumper
MyDumper.add_representer(QuotedString, quoted_scalar)
foo = {
'instance_type': 'test',
'hostname': QuotedString('testhost'), # here the 'magic'
'name': 'foo',
'my_list': [
{'foo': 'test', 'bar': 'test2'},
{'foo': 'test3', 'bar': 'test4'}],
'hello': 'world',
}
print(yaml.dump(foo, Dumper=MyDumper, default_flow_style=False))
Что даст вам:
hello: world hostname: "testhost" instance_type: test my_list: - bar: test2 foo: test - bar: test4 foo: test3 name: foo
Отказ от ответственности: Учитывая выбор, я также предпочитаю модуль Anthon ruamel.yaml
для своих потребностей YAML.
yaml.dump()
что ему, вероятно, не нужно было направлятьyaml.dump()
так, как он делает. А также без использования специфичной для yaml терминологии, которую он вполне может не понять.