PyYAML - сохранение данных на .YAML файлы


Так что я взял PyYAML за последние несколько дней, но я чувствую, что в некоторых документах, является расплывчатым или я неправильно истолковал его. Здесь есть функция для записи данных .в YAML, который может написать значения для каждого элемента у меня в списке:

def writeSave(filename, **kwargs):
    with open(filename, 'r') as yamlFile:
        yamlDict = yaml.load(yamlFile)
        if not yamlDict: yamlDict = {}

    with open(filename, 'w') as write:
        z = yamlDict.copy()
        z.update(kwargs)
        yaml.dump(z, write)

Что тогда будет перезаписывать значения при вызове:

saveData:
        {mission_state: 7, playername: 'steve'}

Используя эту функцию, кажется простым:

writeSave('../path/savedata.yaml', mission_state=2)

Что будет потом изменить mission_state в списке.

Я не знаю, если я сделал это плавно, или если есть лучшая практика, чтобы выполнять такого рода функции. Если есть, было бы неплохо иметь какие-то указатели.

Есть ли способ, чтобы сделать это более удобочитаемым? Может быть более читабельным Варс или более комментируете?



4442
0
задан 3 февраля 2018 в 03:02 Источник Поделиться
Комментарии
1 ответ


  • Во-первых, Python имеет официальный стиль-руководство, PEP8, которым вы должны следовать. Он рекомендует использовать lower_case для функций и переменных.

  • Я бы также переименовать функцию, так как write_save не сказать, что эта функция делает. Я думаю overwrite_setting или update_value или что-то подобное было бы лучше.

  • Вы, возможно, захотите добавить проверку, если какие-либо ключевые аргументы передаются в функцию. Либо вызывают исключение (простой AssertionError может быть достаточно), или, по крайней мере, не тратьте время на чтение файла и писать одно и то же содержимое.

  • А open открывает файл в режиме чтения по умолчанию, вот я думаю, что это на самом деле хорошо, чтобы открыть его один раз прямо с 'r' а потом с 'w'.

  • Ваш z = yamDict.copy() должны быть совершенно ненужными. Мутации исходный словарь не причинить никакого вреда. Обновления не должны быть в пределах with заблокировать либо.

  • Наконец, вы могли бы использовать or для проверки пустой словарь.

При всех вышеперечисленных изменений, ваш код станет:

import yaml

def update_value(filename, **kwargs):
assert kwargs
with open(filename, 'r') as f:
yaml_dict = yaml.load(f) or {}
yaml_dict.update(kwargs)
with open(filename, 'w') as f:
yaml.dump(yaml_dict, f)


Если у вас есть только один поток, вы можете пропустить Чтение конфигурации каждый раз, когда вы хотите изменить значение и вместо того, чтобы держать словарь в памяти (после того, как он когда-то читал в начале). Вы все еще хотите писать, чтобы сохранить государство. Для этого вы, возможно, захотите, чтобы иметь Config класс, производный от dict:

import os

class Config(dict):
def __init__(self, filename):
self.filename = filename
if os.path.isfile(filename):
with open(filename) as f:
# use super here to avoid unnecessary write
super(Config, self).update(yaml.load(f) or {})

def __setitem__(self, key, value):
super(Config, self).__setitem__(key, value)
with open(self.filename, "w") as f:
yaml.dump(self, f)

def __delitem__(self, key):
super(Config, self).__delitem__(key)
with open(self.filename, "w") as f:
yaml.dump(self, f)

def update(self, kwargs):
super(Config, self).update(kwargs)
with open(self.filename, "w") as f:
yaml.dump(self, f)

Возможно, вы захотите определить декоратора, чтобы добавить то, что она бросила методов:

import functools

def dumps(func):
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
ret = func(self, *args, **kwargs)
with open(self.filename, "w") as f:
yaml.dump(self, f)
return ret
return wrapper

class Config(dict):
def __init__(self, filename):
self.filename = filename
if os.path.isfile(filename):
with open(filename) as f:
# use super here to avoid unnecessary write
super(Config, self).update(yaml.load(f) or {})

__setitem__ = dumps(dict.__setitem__)
__delitem__ = dumps(dict.__delitem__)
update = dumps(dict.update)

Вы можете использовать этот класс как dictно каждое изменение в словарь также сваливали в формате YAML файл. Файл только один раз прочитать (если конфиг инициализации), поэтому изменения в файле будут видны только когда скрипт перезапускается.

cfg = Config("test.yaml")
print(cfg)
cfg['a'] = 3
print(cfg)
cfg.update({"b": 4})
cfg.update(c=5)
del cfg['a']
print(cfg)

6
ответ дан 3 февраля 2018 в 12:02 Источник Поделиться