PyYAML выводит данные с использованием ведущих вопросительных знаков для ключей и печатает значения в следующей строке - PullRequest
0 голосов
/ 12 октября 2018

При выводе dict с довольно длинными ключами я получаю что-то вроде этого:

? ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.Data.DateTime.NewDateTime
: 2018-10-11 17:59
? ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.Data.DateTime.SetNewDateTime
: 2018-10-11 17:59
? ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.Data.FeedFlow.Auger[].Ascend
: 2018-10-11 17:59
? ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.Data.FeedFlow.Auger[].Descend
: 2018-10-11 17:59

Вместо этого я бы хотел:

  • не иметь ведущую?для каждого элемента dict
  • нет ключа, напечатанного в следующей строке

Примерно так:

ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.Data.DateTime.NewDateTime: 2018-10-11 17:59
ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.Data.DateTime.SetNewDateTime: 2018-10-11 17:59
ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.Data.FeedFlow.Auger[].Ascend: 2018-10-11 17:59
ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.Data.FeedFlow.Auger[].Descend: 2018-10-11 17:59

Как я могу выполнить вышеизложенное?

Моя текущая команда дампа выглядит следующим образом:

yaml.dump(
    some_dict, 
    open(shades, 'w+'), 
    default_flow_style=False, 
    width=float("inf")
)

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

content = content.replace("? ","")
content = content.replace("\n:",":")

1 Ответ

0 голосов
/ 12 октября 2018

Прежде всего, этот выходной сигнал отлично подходит для YAML.Я загружаю обратно к тому, что вы сбросили.Это выглядит не очень хорошо, но это необходимо сделать, потому что ключи длинные и не соответствуют длине строки по умолчанию.

Вы предоставляете параметр width, но проблема в том, чтоfloat("inf") не является подходящим значением, и PyYAML не предупреждает вас об этом.Вместо этого вы должны просто использовать достаточно большое целое число , как показано в следующем коде (при условии, что данные находятся в файле shades.yaml):

import sys
import yaml

ONEMILLION = 1000**2

with open('shades.yaml') as fp:
    data = yaml.safe_load(fp)
yaml.safe_dump(data, sys.stdout, default_flow_style=False, width=ONEMILLION)

output:

ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.Data.DateTime.NewDateTime: 2018-10-11 17:59
ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.Data.DateTime.SetNewDateTime: 2018-10-11 17:59
ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.Data.FeedFlow.Auger[].Ascend: 2018-10-11 17:59
ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.Data.FeedFlow.Auger[].Descend: 2018-10-11 17:59

И нет, вы не можете сделать ONEMILLION = int(float("inf")), вы получите ошибку.

Я использую safe_dump здесь, не потому, что это необходимо, а достаточно, и потому что это снижает вероятность того, что вы используете load(), что в PyYAML потенциально небезопасно.


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

from pathlib import Path
import ruamel.yaml

shades = Path('shades.yaml')

yaml = ruamel.yaml.YAML()
yaml.width = ONEMILLION
# next line is not necessary, style is preserved and input is block-style
yaml.default_flow_style=False  
data = yaml.load(shades)
yaml.dump(data, sys.stdout)

с тем же результатом.

...