В Python есть очень удобный модуль для сохранения и чтения ini-подобных конфигурационных файлов, который называется ConfigParser.
У меня при его использовании возникла проблема, связанная с сохранением в файл Unicode-строк. В некоторых трудноуловимых случаях (например, у меня это проявилось при работе приложения под Windows XP) при чтении или записи таких параметров выскакивает ошибка конвертации строк.
В интернете мне не удалось найти готовых решений, хотя вопросов о том «как сделать чтобы всегда работало» довольно много — обычно отвечают в духе «просите автора модуля это исправить».
Хочу предложить свое решение для тех, кто использует Python 2.X — оно довольно простое и помогает решить эту проблему.
Во-первых, нужно унаследовать класс RawConfigParser, переопределив метод write() — а именно — заменив все вызовы str() на вызовы unicode():
Во-вторых, запись и чтение конфигурационного файла нужно делать с оберткой для open() из модуля codecs, которой нужно указать utf-8 в качестве кодировки. В случае загрузки это можно сделать, если использовать для чтения не read(), а readfp():
Надеюсь, кому-нибудь пригодится. Если у вас есть более красивое и удачное решение, буду рад его услышать.
У меня при его использовании возникла проблема, связанная с сохранением в файл Unicode-строк. В некоторых трудноуловимых случаях (например, у меня это проявилось при работе приложения под Windows XP) при чтении или записи таких параметров выскакивает ошибка конвертации строк.
В интернете мне не удалось найти готовых решений, хотя вопросов о том «как сделать чтобы всегда работало» довольно много — обычно отвечают в духе «просите автора модуля это исправить».
Хочу предложить свое решение для тех, кто использует Python 2.X — оно довольно простое и помогает решить эту проблему.
Во-первых, нужно унаследовать класс RawConfigParser, переопределив метод write() — а именно — заменив все вызовы str() на вызовы unicode():
Copy Source | Copy HTML
- class UnicodeConfigParser(ConfigParser.RawConfigParser):
-
- def __init__(self, *args, **kwargs):
- ConfigParser.RawConfigParser.__init__(self, *args, **kwargs)
-
- def write(self, fp):
- """Fixed for Unicode output"""
- if self._defaults:
- fp.write("[%s]\n" % DEFAULTSECT)
- for (key, value) in self._defaults.items():
- fp.write("%s = %s\n" % (key, unicode(value).replace('\n', '\n\t')))
- fp.write("\n")
- for section in self._sections:
- fp.write("[%s]\n" % section)
- for (key, value) in self._sections[section].items():
- if key != "__name__":
- fp.write("%s = %s\n" %
- (key, unicode(value).replace('\n','\n\t')))
- fp.write("\n")
-
- # This function is needed to override default lower-case conversion
- # of the parameter's names. They will be saved 'as is'.
- def optionxform(self, strOut):
- return strOut
-
Во-вторых, запись и чтение конфигурационного файла нужно делать с оберткой для open() из модуля codecs, которой нужно указать utf-8 в качестве кодировки. В случае загрузки это можно сделать, если использовать для чтения не read(), а readfp():
Copy Source | Copy HTML
- import codecs
-
- # Saving
-
- confFile = codecs.open('myConfig.ini', 'w', 'utf-8')
- config = UnicodeConfigParser()
- # ...
- config.write(confFile)
- confFile.close()
-
- # Loading
-
- config = UnicodeConfigParser()
- config.readfp(codecs.open('myConfig.ini', "r", "utf-8"))
Надеюсь, кому-нибудь пригодится. Если у вас есть более красивое и удачное решение, буду рад его услышать.