Я использую файлы конфигурации через configparser в python3.7.1.
У меня есть переменная в одном из файлов, которые я бы хотел изменить во время выполнения. Интересно, что это лучший способ сделать это.
Сейчас я переписываю весь файл так:
config = configparser.ConfigParser()
config.read('config.ini')
config['Categorie']['new_variable'] = variable
with open('config.ini', 'w') as configfile:
config.write(configfile)
У меня есть 2 проблемы с этим методом:
-potentially потеря конфигурации при ошибке
-deleting комментарии в файле каждый раз
Другой метод состоял бы в том, чтобы иметь два файла, один из которых будет выделен для измененных переменных времени выполнения
configparser
не хранит комментарии, поэтому вы застряли на этом, если вы не используете этот модуль... Или вы можете извлечь комментарии и повторно добавить их в файл после этого (потеря позиции комментариев, но сохранение содержание)
Чтобы избежать потери конфигурации в случае ошибки (полный диск или другой), вы можете сохранить как другое имя, удалить текущий файл и переименовать.
conf_file = 'config.ini'
with open(conf_file+'.bak', 'w') as configfile:
config.write(configfile)
if os.path.exists(conf_file):
os.remove(conf_file) # else rename won't work when target exists
os.rename(conf_file+'.bak',conf_file)
этот метод безопасен. Если файл не может быть записан, предыдущий файл не сбивается. Худший случай (если кто-то вытаскивает вилку в тот момент, когда удаляется исходный файл), остается файл .bak
(с соответствующим новым содержимым).
Альтернативой было бы переименование существующего файла.ini, запись нового и удаление старого.ini файла, когда файл был успешно записан.
Все операции выполняются на одном диске, поэтому больше нет доступа к диску (за исключением переименования), даже если файл огромен.
config.ini
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = {somelevel}
ForwardX11 = yes
код python
content = open('config.ini').read()
somelevel = 34
filled = content.format(**locals())
gg = ConfigParser()
gg.read_string(filled)
Однако НЕ используйте ** locals() для реального кода. Попытайтесь найти лучший способ, это грязно.
edit: Я попробовал сделать некоторые простые флеш-хаки, они не работают из-за проблем.
configparser
ruamel.yaml
. Что касается безопасного обновления - запишите новый файл (например,file.new
), удалите старый (т.е.file.conf
), переименуйте новый в имя по умолчанию (т.е.file.conf
). При чтении конфигурации попытайтесь прочитать имя по умолчанию (file.conf
), если оно недоступно, попробуйте прочитать новую конфигурацию (file.new
) на случай, если переименование не удалось выполнить при последнем обновлении. В качестве альтернативы, используйте базу данных (sqlite
должно быть хорошо) для вашей конфигурации и полагайтесь на механизм БД для атомарности.