Возникли проблемы с выходом из одинарной кавычки

Мне трудно избежать одинарных кавычек при добавлении новых значений в yaml с помощью ruamel.yaml.

Ниже то, что я делаю

import sys
from ruamel.yaml import YAML

yaml_doc = """\
Mappings:
  Values:
    '123': 'no'
"""

yaml = YAML()
yaml.preserve_quotes = True
data = yaml.load(yaml_doc)

new_value = data['Mappings']['Values']
new_value.insert(len(new_value), '456','' 'no'' ', comment="New Value")
new_value.insert(len(new_value), '789',' ''no' '', comment="New Value 2")
yaml.dump(data, sys.stdout)

С этим кодом я всегда получаю начальный или конечный пробел после/перед нет для значений, которые я вставил.

Mappings:
  Values:
    '123': 'no'
    '456': 'no '  # New Value
    '789': ' no' # New Value 2

Как я могу вставить значение без одинарных кавычек, но без пробела в конце/заголовке?


person André Santos    schedule 21.05.2019    source источник
comment
экранируйте с помощью \ или используйте   -  person Smart Manoj    schedule 21.05.2019
comment
'no'' ' = 'no'+' ' = 'no ' Используйте "нет" или "нет\"   -  person Smart Manoj    schedule 21.05.2019
comment
Вы хотите выразить значение, содержащее кавычки, или вы просто хотите выразить строку no, используя синтаксис с кавычками…?   -  person deceze♦    schedule 21.05.2019
comment
stackoverflow.com/questions/4630465/   -  person Peter Wood    schedule 21.05.2019
comment
Возможный дубликат Как включить цитату в необработанный Python строка?   -  person Dave    schedule 21.05.2019


Ответы (3)


Если бы вы попытались:

print(repr('' 'no'' '))

это даст вам:

'no '

так как вы сопоставляете строку '' со строкой 'no' и строкой ' ', которую Python просто объединяет в 'no ' перед вызовом print. То, что вы пытаетесь сделать, это использовать скалярный механизм экранирования одинарных кавычек YAML в Python, и это будет работать, только если вы YAML().load() строку из YAML.

Если вы хотите, чтобы на выходе был один скаляр в кавычках, как и на входе, вы должны сделать скаляр того же типа, что и то, что вы получаете, используя .load(). Это ruamel.yaml.scalarstring.SingleQuotedScalarString (как подкласс string).

import sys
from ruamel.yaml import YAML
from ruamel.yaml.scalarstring import SingleQuotedScalarString as sq

yaml_doc = """\
Mappings:
  Values:
    '123': 'no'
"""

yaml = YAML()
yaml.preserve_quotes = True
data = yaml.load(yaml_doc)

new_value = data['Mappings']['Values']
new_value['456'] = sq('no')
new_value.yaml_add_eol_comment(comment="New Value", key='456', column=0)
new_value.insert(len(new_value), '789', sq('no'), comment="New Value 2")
yaml.dump(data, sys.stdout)

это дает:

Mappings:
  Values:
    '123': 'no'
    '456': 'no' # New Value
    '789': 'no' # New Value 2
person Anthon    schedule 21.05.2019
comment
Вам нужно использовать yaml_add_eol_comment для первого добавленного значения, иначе вы получите дополнительное пространство перед комментарием (а .insert не имеет возможности установить столбец). Не уверен, что там происходит, возможно, небольшая ошибка. - person Anthon; 21.05.2019
comment
Я не понимаю, почему вы проделываете всю эту работу, чтобы иметь 'no' в своем YAML против no. Они означают одно и то же. Вот почему это упражнение было так трудно понять вам и другим. В любом случае при анализе файла вы получите количество no без кавычек. Если вы понимаете синтаксис YAML, все становится очень просто. - person CryptoFool; 22.05.2019
comment
Есть ли у вас причина заботиться о том, что находится в вашем YAML, помимо того, что он выдаст при разборе надлежащим интерпретатором YAML? Вы хотите, чтобы число 'no' считывалось синтаксическим анализатором YAML и сохранялось в кавычках? В настоящее время этого не произойдет. - person CryptoFool; 22.05.2019
comment
@Steve В вашем комментарии есть несколько ложных утверждений. Они означают одно и то же для правильного, актуального синтаксического анализа YAML, например. ruamel.yaml и другие парсеры YAML 1.2. Хотя спецификация отсутствует уже десять лет, некоторые люди и проекты все еще используют синтаксические анализаторы, основанные на спецификации YAML 1.1, и для них no загружается как логическое значение, а 'no' как строка. Сохранение таких кавычек при загрузке-изменении-дампе, будь то для эстетики или для предотвращения ложных изменений в файле, находящемся под контролем версий, что в настоящее время произойдет, если вы используете ruamel.yaml. - person Anthon; 22.05.2019
comment
@ Антон, это хорошие моменты. В моих комментариях нет ложных утверждений относительно текущей спецификации YAML. Я совершил ошибку, не допустив, что старые версии YAML могут отличаться. Спасибо за обучение меня там. Я все еще думаю, что прыгать через обручи, чтобы написать простой файл YAML таким образом, выглядит как запах кода. А что касается проверки сгенерированного YAML-файла, то это нарушает принцип DRY. Но ни в чем из этого я не допускаю, что могут быть веские причины для всего этого. Отсюда мой второй комментарий, который был вопросом, и вы как бы отвечаете на него. - person CryptoFool; 23.05.2019
comment
Обратите внимание, что ОП не говорит, требуется ли ему YAML, поддерживающий устаревший синтаксический анализатор. На самом деле он может быть дезинформирован относительно разницы между двумя форматами (или, скорее, ее отсутствия), и поэтому фраза «не беспокойтесь о кавычках» может быть как раз правильным ответом. Кто знает. Я просто предлагал другую точку зрения, помимо слепого написания кучи непонятного кода для создания чего-то сомнительного назначения. - person CryptoFool; 23.05.2019

Я не уверен, что полностью понял, о чем вы спрашиваете, но вы просто вставили 3 строки для значения и объединили их. В

new_value.insert(len(new_value), '456','' 'no'' ', comment="New Value")

Часть '' 'no'' ' переводится как ''=<Empty String> 'no'=no ' '=<Space>.

Итак, если вам нужен обычный 'no', просто выполните:

new_value.insert(len(new_value), '456','no', comment="New Value")
person andreygold    schedule 21.05.2019
comment
Это не дает OP 'no' в его документе YAML, как он явно просит (см. последнюю строку поста), а просто no - person Anthon; 21.05.2019
comment
легко регулируется с помощью new_value.insert(len(new_value), '456','\'no\'', comment="New Value") - person andreygold; 21.05.2019
comment
Это на самом деле даст вам "'no'" в вашем документе YAML. Хотя это одинарные кавычки вокруг no, я предполагаю, что ОП хочет, чтобы строки были похожи на последнюю строку его входного документа. - person Anthon; 21.05.2019
comment
Вы уверены, что new_value.insert(len(new_value), '456','no', comment="New Value") не сделает то, что хочет? у него этот флаг на yaml.preserve_quotes = True - person andreygold; 21.05.2019
comment
Да, я уверен. 1) Сохранение работает только с материалом, загруженным из документа YAML (для сохранения он должен быть там в первую очередь) 2) Я хорошо знаком с внутренностями ruamel.yaml. 3) Я попробовал код, а затем скопировал результат в свой предыдущий комментарий ;-) - person Anthon; 21.05.2019

ОБНОВЛЕНИЕ: @Anthon сообщил мне, что более ранние версии YAML будут рассматривать no и 'no' как разные значения, считая no логическое значение. Поэтому, пожалуйста, принимайте то, что я говорю ниже, только как относящееся к текущей версии YAML. Кроме того, возможно, здесь есть еще одна мотивация, помимо написания YAML, которая даст определенный результат от современного синтаксического анализатора. В этом случае у вас есть хороший ответ выше от @Anthon о том, как принудительно включить эти кавычки в результирующий YAML через писатель, который не может учитывать старый формат YAML (я бы посоветовал убедиться, что такого нет режим в писателе).

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

Здесь я не уверен, чего хочет ОП. Похоже, он либо хочет, чтобы слово no несколько раз встречалось в структуре данных, которую представляет его YAML, либо, может быть, он хочет, чтобы 'no' было значением, которое заканчивается в структуре данных. Вот самые краткие способы написания каждого из них (в YAML 1.2):

нет == no

'нет' == "'no'"

Здесь нет случая, когда символы 'no' должны отображаться в YAML так, как пытается заставить OP. Весь этот дополнительный код пытается принудительно вставить эти символы в YAML, когда в этом нет необходимости. Эта конструкция означает то же самое, что и no. Просто забудьте о кавычках.

person CryptoFool    schedule 22.05.2019