Почему * * kwargs не интерполируется с помощью python ConfigObj?


Я использую ConfigObj в python с интерполяцией в стиле шаблона. Разворачивание моего конфигурационного словаря через **, похоже, не делает интерполяцию. Это особенность или ошибка? Есть хорошие обходные пути?

$ cat my.conf
foo = /test
bar = $foo/directory

>>> import configobj
>>> config = configobj.ConfigObj('my.conf', interpolation='Template')
>>> config['bar']
'/test/directory'
>>> '{bar}'.format(**config)
'$foo/directory'

Я бы ожидал, что вторая строка будет /test/directory. Почему интерполяция не работает с * * кваргами?

2 7

2 ответа:

При распаковке аргумента ключевого слова создается новый объект: типа dict. Этот словарь содержит необработанные значения конфигурации (без интерполяции)

Демонстрация:

>>> id(config)
31143152
>>> def showKeywordArgs(**kwargs):
...     print(kwargs, type(kwargs), id(kwargs))
...
>>> showKeywordArgs(**config)
({'foo': '/test', 'bar': '$foo/directory'}, <type 'dict'>, 35738944)

Чтобы решить эту проблему, вы можете создать расширенную версию конфигурации следующим образом:

>>> expandedConfig = {k: config[k] for k in config}
>>> '{bar}'.format(**expandedConfig)
'/test/directory'
Еще один более элегантный способ-это просто избежать распаковки: это может быть достигнуто с помощью функции string.Форматер.vformat :
import string
fmt = string.Formatter()
fmt.vformat("{bar}", None, config)

У меня была аналогичная проблема.

Обходной путь заключается в использовании функции configobj ".словарь()". Это работает, потому что configobj возвращает реальный словарь, который Python знает, как распаковать.

Ваш пример становится:

>>> import configobj
>>> config = configobj.ConfigObj('my.conf', interpolation='Template')
>>> config['bar']
'/test/directory'
>>> '{bar}'.format(**config.dict())
'/test/directory'