PyYAML сбрасывает логическое значение

Я загружаю элемент yaml True/False (пример ниже) из файла YAML.

gzip: False

Это правильно интерпретируется в шаблоне Jinja2 как логическое значение True.

Тот же файл YAML читается другим скриптом, передается как данные формы Python CGI и в конечном итоге записывается в файл YAML с использованием

with open(myyaml, 'w') as yaml_file:
    yaml_file.write(yaml.dump(dict, default_flow_style=False)) 

Проблема в том, что это затем записывает True/False с одинарной кавычкой

gzip: 'False'

что приводит к тому, что шаблон jinja2 не интерпретирует значение как логическое и всегда устанавливает значение как истинное в

{{ if gzip }}

Есть ли способ сбросить файл YAML со значениями True/False, которые обрабатываются как логические (я имею в виду без кавычек).


person Anoop P Alias    schedule 03.11.2016    source источник
comment
Конечно, он не будет автоматически анализировать строку 'False' как логическое значение. В этом нет ничего особенного ни для Jinja2, ни для YAML. Это везде одно и то же. Как он должен знать, что вы хотите проанализировать значение? Вам придется сделать это явно, если ваши данные не хранятся должным образом в файле YAML.   -  person poke    schedule 03.11.2016
comment
Проблема в том, что кавычки добавляет yaml.dump. Первоначально, когда я создаю yaml, в нем нет кавычек, или вопрос можно перефразировать как «Как я могу сбросить значение в yaml, явно указав его как логическое, а не как строку». Я думаю, что form.get преобразует True/False в строку.   -  person Anoop P Alias    schedule 03.11.2016
comment
yaml.dump не выводит логическое значение в виде строки, если раньше оно было фактическим логическим значением: yaml.dump({ 'Foo': 'Bar', 'Baz': True }) дает вам '{Baz: true, Foo: Bar}\n' — без кавычек. В любом случае YAML спроектирован так, чтобы в основном не цитировать.   -  person poke    schedule 03.11.2016


Ответы (1)


.dump() просто сбрасывает данные, которые он получает, и он должен получить строку вместо логического значения в качестве значения для ключа gzip. Поскольку это строковое значение, если оно выгружено без кавычек, может быть неверно истолковано как логическое значение, оно будет заключено в кавычки.

Поскольку вы получаете свой материал из формы CGI, любое значение True или False будет строкой. Прежде чем сбрасывать ваши данные, вы явно должны преобразовать эти значения, полученные из CGI, в логические значения.

Вы можете пройтись по своему словарю и сделать что-то общее, прежде чем dump:

import sys
import yaml

# simulating getting string type values from CGI
data = dict(gzip='False', intval="1", strval="abc") 

for k in data:
    v = data[k]
    try:
        v = int(v)
        data[k] = v
    except ValueError:
        vl = v.lower()
        if vl == 'false':
            data[k] = False
        elif vl == 'true':
            data[k] = True

yaml.safe_dump(data, sys.stdout, default_flow_style=False)

дает:

gzip: false
intval: 1
strval: abc

Обратите внимание, что abc не заключено в кавычки, потому что его нельзя интерпретировать как что-либо еще, кроме строки. Вышеприведенное, конечно, также преобразует строки «True» или «False», которые должны оставаться строками. Если это не то, что вы хотите, вы должны выбрать преобразование на основе ключа.

Есть две другие серьезные проблемы с вашими двумя строками Python:

with open(myyaml, 'w') as yaml_file:
    yaml_file.write(yaml.dump(dict, default_flow_style=False)) 
  1. Вы никогда не должны использовать ключевое слово Python (dict) в качестве имени переменной, это просто вызовет проблемы в дальнейшем в вашем коде.
  2. yaml.dump() выгружает данные в поток. У него есть возможность: если вы не укажете поток, в который должны идти вещи, вывод записывается во внутренний объект потока, из которого возвращается окончательное значение. Вы не должны злоупотреблять этим, чтобы затем записать это возвращаемое значение в файл yaml_file. Вместо этого выполните:

    with open(myyaml, 'w') as yaml_file:
        yaml.dump(dict, yaml_file, default_flow_style=False))
    

    Ваш способ неэффективен (не считая непонимания).

person Anthon    schedule 03.11.2016
comment
Ключевое слово dict не использовалось. Я просто хочу быстро сказать, что в коде использовался словарь. Спасибо, что указали на проблему с моим стилем yaml.dump. Я приму ваш ответ, так как форма действительно получала строковое значение вместо логического. - person Anoop P Alias; 03.11.2016
comment
@AnoopPAlias ​​Извините за неправильное толкование dict. Я могу порекомендовать использовать что-то вроде my_dict в таких случаях. Вы всегда будете видеть, что следующий посетитель скопирует и вставит ваш код, и он будет работать до тех пор, пока ключевое слово не понадобится использовать по назначению (конечно, кто-то еще будет поддерживать код через несколько лет) :-). - person Anthon; 03.11.2016