Преобразование значений ConfigParser в типы данных python

#python #eval #configparser

#python #eval #configparser

Вопрос:

ConfigParser требует, чтобы все разделы, ключи и значения были строками; неудивительно. В нем есть методы для преобразования значений в типы данных с помощью getfloat , getint getboolean . Если вы не знаете тип данных, вы можете обернуть get() с eval() , чтобы получить вычисленную строку, такую как:

 >>> from ConfigParser import SafeConfigParser
>>> cp = SafeConfigParser()
>>> cp.add_section('one')
>>> cp.set('one', 'key', '42')
>>> print cp.get('one', 'key')
'42'
>>> print eval(cp.get('one', 'key'))
42
>>> cp.set('one', 'key', 'None')
>>> print eval(cp.get('one', 'key'))
None
>>> 
  

Есть ли способ лучше? Я предполагаю, что существуют серьезные проблемы с безопасностью при оценке текста из файла — что я признаю; Я полностью доверяю файлу.

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

Как бы вы это сделали?

Ответ №1:

Если вы используете Python 2.6 или выше, вы можете использовать ast.literal_eval :

ast.literal_eval(node_or_string)
Безопасно вычисляйте узел выражения или строку, содержащую выражение Python. Предоставленная строка или узел могут состоять только из следующих литеральных структур Python: строк, чисел, кортежей, списков, dicts, логических значений и None.

Это можно использовать для безопасного вычисления строк, содержащих выражения Python из ненадежных источников, без необходимости самостоятельного анализа значений.

Это будет работать так же, как eval когда строка безопасна:

 >>> literal_eval("{'key': 10}")
{'key': 10}
  

Но это приведет к сбою, если появится что-либо, кроме типов, перечисленных в документации:

 >>> literal_eval("import os; os.system('rm -rf somepath')")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.6/ast.py", line 49, in literal_eval
    node_or_string = parse(node_or_string, mode='eval')
  File "/usr/lib64/python2.6/ast.py", line 37, in parse
    return compile(expr, filename, mode, PyCF_ONLY_AST)
  File "<unknown>", line 1
    import os; os.system('rm -rf somepath')
         ^
SyntaxError: invalid syntax
  

Комментарии:

1. я использовал ваш ответ для создания этого: codereview.stackexchange.com/questions/2775 /…

Ответ №2:

Для тех, кто, возможно, ищет другой более простой ответ, вместо того, чтобы самостоятельно преобразовывать типы данных, вы можете использовать модуль localconfig, который выполняет преобразование за вас. Преобразование выполняется путем угадывания типа данных на основе значения (т.е. 123 — это int, 123.4 — это float, true — это bool и так далее).

Вот пример, следующий за OP:

 >>> from localconfig import config
>>> config.read('[one]nkey = 42nkey2 = None')
>>> config.one.key, type(config.one.key)
(42, <type 'int'>)
>>> config.one.key2, type(config.one.key2)
(None, <type 'NoneType'>)
>>> config.get('one', 'key'), config.get('one', 'key2')
(42, None)
  

Это оболочка поверх ConfigParser, поэтому она полностью совместима.

Проверьте это на https://pypi.python.org/pypi/localconfig

Комментарии:

1. Спасибо, ваши пакеты были очень полезны для меня!

Ответ №3:

Вот еще одно решение. Вы можете сгенерировать getany() метод, который автоматически определит и вернет правильный тип данных для большинства типов, включая str , int , float bool и None .

Обратите внимание, что для этого обозначения в файле конфигурации должны быть Python. например, True для логических значений true и None для значений null.

 from ast import literal_eval
import configparser

parser = configparser.ConfigParser(converters={"any": lambda x: literal_eval(x)})
value = parser.getany("section", "key")
# ...
  

Ответ №4:

Если вы используете версию 2.7 , вы можете использовать .getint .getfloat .getbool методы. Вы можете узнать больше о них в документах

Таким образом, ваше приложение будет использовать print cp.getint('one', 'key')

Ответ №5:

Проверьте ConfigIt для получения дополнительных параметров конфигурации pythonic

https://github.com/barberj/ConfigIt