Pull to refresh

ConfigParser и Unicode

Python *
В Python есть очень удобный модуль для сохранения и чтения ini-подобных конфигурационных файлов, который называется ConfigParser.

У меня при его использовании возникла проблема, связанная с сохранением в файл Unicode-строк. В некоторых трудноуловимых случаях (например, у меня это проявилось при работе приложения под Windows XP) при чтении или записи таких параметров выскакивает ошибка конвертации строк.

В интернете мне не удалось найти готовых решений, хотя вопросов о том «как сделать чтобы всегда работало» довольно много — обычно отвечают в духе «просите автора модуля это исправить».

Хочу предложить свое решение для тех, кто использует Python 2.X — оно довольно простое и помогает решить эту проблему.



Во-первых, нужно унаследовать класс RawConfigParser, переопределив метод write() — а именно — заменив все вызовы str() на вызовы unicode():

Copy Source | Copy HTML
  1. class UnicodeConfigParser(ConfigParser.RawConfigParser):
  2.  
  3.     def __init__(self, *args, **kwargs):
  4.         ConfigParser.RawConfigParser.__init__(self, *args, **kwargs)
  5.  
  6.     def write(self, fp):
  7.         """Fixed for Unicode output"""
  8.         if self._defaults:
  9.             fp.write("[%s]\n" % DEFAULTSECT)
  10.             for (key, value) in self._defaults.items():
  11.                 fp.write("%s = %s\n" % (key, unicode(value).replace('\n', '\n\t')))
  12.             fp.write("\n")
  13.         for section in self._sections:
  14.             fp.write("[%s]\n" % section)
  15.             for (key, value) in self._sections[section].items():
  16.                 if key != "__name__":
  17.                     fp.write("%s = %s\n" %
  18.                              (key, unicode(value).replace('\n','\n\t')))
  19.             fp.write("\n")
  20.  
  21.     # This function is needed to override default lower-case conversion
  22.     # of the parameter's names. They will be saved 'as is'.
  23.     def optionxform(self, strOut):
  24.         return strOut
  25.  


Во-вторых, запись и чтение конфигурационного файла нужно делать с оберткой для open() из модуля codecs, которой нужно указать utf-8 в качестве кодировки. В случае загрузки это можно сделать, если использовать для чтения не read(), а readfp():

Copy Source | Copy HTML
  1. import codecs
  2.  
  3. # Saving
  4.  
  5. confFile = codecs.open('myConfig.ini', 'w', 'utf-8')
  6. config = UnicodeConfigParser()
  7. # ...
  8. config.write(confFile)
  9. confFile.close()
  10.  
  11. # Loading
  12.  
  13. config = UnicodeConfigParser()
  14. config.readfp(codecs.open('myConfig.ini', "r", "utf-8"))


Надеюсь, кому-нибудь пригодится. Если у вас есть более красивое и удачное решение, буду рад его услышать.
Tags:
Hubs:
Total votes 29: ↑25 and ↓4 +21
Views 15K
Comments 14
Comments Comments 14

Posts