Python YAML hiera и как значение может быть внутри двойных кавычек?

у меня есть этот код

python_data_struct = {
        'amazon_app_id': amazon_app_id,
        'librivox_rest_url': librivox_rest_url,
        'librivox_id': librivox_id,
        'top': top,
        'pacakge': 'junk',
        'version': 'junk',
        'password': password,
        'description': description,
        'long_description': long_description,
        'make_audiobook::sftp_script::appname': '\"%{::appname}\"'
}
try:
        myyaml = yaml.dump(python_data_struct)
except:
        e = sys.exc_info()[0]
        print "Error on %s Error [%s]" % ( librivox_rest_url, e )
        sys.exit(5)
write_file( myyaml, hiera_dir + '/' + appname + '.yaml' );

Он выводит yaml, который выглядит так:

{amazon_app_id: junk, description: !!python/unicode ' Riley was an American writer
    known as the "Hoosier poet", and made a start writing newspaper verse in Hoosier
    dialect for the Indianapolis Journal in 1875. His favorite authors were Burns
    and Dickens. This collection of poems is a romanticized and mostly boy-centered
    paean to a 19th century rural American working-class childhood. (Summary by Val
    Grimm)', librivox_id: '1000', librivox_rest_url: 'https://librivox.org/api/feed/audiobooks/id/1000/extended/1/format/json',
  long_description: !!python/unicode "\n Riley was an American writer known as the\
    \ \"Hoosier poet\", and made a start writing newspaper verse in Hoosier dialect\
    \ for the Indianapolis Journal in 1875. His favorite authors were Burns and Dickens.\
    \ This collection of poems is a romanticized and mostly boy-centered paean to\
    \ a 19th century rural American working-class childhood. (Summary by Val Grimm)\n\
    \nThe \"Selected Riley Child-Rhymes\" App will not use up your data plan's minutes\
    \ by downloading the audio files (mp3) over and over. You will download load all\
    \ the data when you install the App. The \"Selected Riley Child-Rhymes\" App works\
    \ even in airplane mode and in places without Wi-Fi or phone network access! So\
    \ you can listen to your audio book anywhere anytime! The \"Selected Riley Child-Rhymes\"\
    \ App automatically pauses when you make or receive a phone call and automatically\
    \ resumes after the call ends. The \"Selected Riley Child-Rhymes\" App will continue\
    \ to play until you exit the App or pause the reading so it is perfect for listening\
    \ in bed, at the gym, or while driving into work.\" \n", 'make_audiobook::sftp_script::appname': '"%{::appname}"',
  pacakge: junk, password: junk, top: junk, version: junk}

Трудно увидеть, но конкретная пара ключ/значение, которая является проблемой, такова:

'make_audiobook::sftp_script::appname': '"%{::appname}"',

Мне нужно, чтобы это было так:

'make_audiobook::sftp_script::appname': "%{::appname}",

Просто двойные кавычки вокруг %{::appname} Я не могу понять, что делать в моем коде Python. Пожалуйста помоги :)


person Red Cricket    schedule 24.03.2017    source источник


Ответы (2)


Если вам нужна строка в YAML, вам просто нужна строка в Python:

python_data_struct = {
    'make_audiobook::sftp_script::appname': '%{::appname}'
}

print yaml.dump(python_data_struct)

Что дает вам:

{'make_audiobook::sftp_script::appname': '%{::appname}'}

Или, что то же самое, с default_flow_style=False:

make_audiobook::sftp_script::appname: '%{::appname}'

В YAML нет разницы между "a value" с использованием двойных кавычек и 'a value' с использованием одинарных кавычек. Этот:

my_key: 'my value'

И это:

my_key: "my value"

Оба будут оценивать одну и ту же структуру данных.

person larsks    schedule 24.03.2017
comment
Не тогда, когда файл yaml должен использоваться hiera. Я планирую использовать этот файл yaml в качестве данных hiera для класса марионеток. %{::appname} — это марионеточный факт, который будет оценивать hiera. '%{::appname}' — буквальная строка. Спасибо за публикацию ответа, хотя :) - person Red Cricket; 24.03.2017
comment
@RedCricket Если hiera не реализует свой собственный синтаксис, подобный YAML, это невозможно. "%{::appname}" и '%{::appname}' — это одно и то же в YAML, и если эти значения обрабатываются по-разному, это является нарушением спецификации YAML и должно быть сообщено как ошибка. В документах говорится: «В файлах YAML любые строка, содержащая токен интерполяции, должна быть заключена в кавычки.“. Они не говорят в двойных кавычках. - person flyx; 24.03.2017
comment
Я сам использую hiera и могу подтвердить, что это просто YAML. Одинарные кавычки, двойные кавычки просто не имеют значения. - person larsks; 24.03.2017
comment
Вроде бы так и есть, но меня это беспокоит. Как заставить hiera оценивать что-либо до буквального %{::puppet_fact_foo} ? Но это другой вопрос. - person Red Cricket; 24.03.2017
comment
И вот этот вопрос: stackoverflow.com/questions/43005412/ - person Red Cricket; 24.03.2017

Если вам нужно управлять кавычками в дампе Python YAML, я рекомендую использовать ruamel.yaml ( Отказ от ответственности: я являюсь автором этого пакета)

import sys
from ruamel import yaml

amazon_app_id = 'junk'
librivox_rest_url = 'https://librivox.org/api/feed/audiobooks/id/1000/extended/1/format/json'

python_data_struct = {
        'amazon_app_id': amazon_app_id,
        'librivox_rest_url': librivox_rest_url,
        'pacakge': 'junk',
        'version': 'junk',
        yaml.scalarstring.SingleQuotedScalarString('make_audiobook::sftp_script::appname'):
            yaml.scalarstring.DoubleQuotedScalarString('%{::appname}')
}

try:
    with open(hiera_dir + '/' + appname + '.yaml') as fp:
        yaml.round_trip_dump(python_data_struct, fp)
except Exception as e:
    print("Error on {} Error [{}]".format(librivox_rest_url, e))
    sys.exit(5)

что дает вам:

librivox_rest_url: https://librivox.org/api/feed/audiobooks/id/1000/extended/1/format/json
version: junk
'make_audiobook::sftp_script::appname': "%{::appname}"
amazon_app_id: junk
pacakge: junk

Обратите внимание, что PyYAML по умолчанию заключает в кавычки скаляры со встроенным ':', даже если за этим символом не следует пробел, хотя это и не обязательно.

Также нельзя использовать второй параметр для round_trip_dump()dump() тоже есть этот параметр). Крайне неэффективно не предоставлять этот параметр и сначала создавать файл YAML в памяти.

Я также изменил часть вашего другого кода, если вы не застряли на Python 2.6 или около того, вам следует IMO модернизировать свой синтаксис. Вы также можете посмотреть имена ключей (вы действительно имели в виду «pacakge»?)

person Anthon    schedule 24.03.2017
comment
Если OP необходимо контролировать кавычки в сгенерированном YAML, что-то очень неправильно. - person larsks; 24.03.2017
comment
@larsks Я согласен, но если ОП не контролирует использование YAML, единственное, что нужно сделать, это попытаться выполнить требования. - person Anthon; 24.03.2017