Интерфейс Python ConfigParser из иностранного раздела - PullRequest
15 голосов
/ 30 сентября 2011

С Python ConfigParser, возможно ли использовать интерполяцию по сторонним разделам? Кажется, мой разум говорит мне, что я видел, что это где-то возможно, но я не могу найти его при поиске.

Этот пример не работает, но он дает представление о том, что я пытаюсь сделать.

[section1]
root = /usr

[section2]
root = /usr/local

[section3]
dir1 = $(section1:root)/bin
dir2 = $(section2:root)/bin

Обратите внимание, что я использую Python 2.4.

Ответы [ 4 ]

12 голосов
/ 30 сентября 2011

В Python 3.2 и выше это совершенно правильно:

[Common]
home_dir: /Users
library_dir: /Library
system_dir: /System
macports_dir: /opt/local

[Frameworks]
Python: 3.2
path: ${Common:system_dir}/Library/Frameworks/

[Arthur]
nickname: Two Sheds
last_name: Jackson
my_dir: ${Common:home_dir}/twosheds
my_pictures: ${my_dir}/Pictures
python_dir: ${Frameworks:path}/Python/Versions/${Frameworks:Python}

Редактировать:

Я только что увидел, что вы используете Python 2,4 , поэтому нет , интерполяция секций не может быть выполнена в python 2.4 .Он был введен в python 3.2 - См. Раздел 13.2.5 - Интерполяция значений ConfigParser .

class configparser.ExtendedInterpolation

Альтернативный обработчик для интерполяции, который реализует более продвинутый синтаксис, используемый, например, в zc.buildout.Расширенная интерполяция использует $ {section: option} для обозначения значения из стороннего раздела.Интерполяция может охватывать несколько уровней.Для удобства, если section: part не указан, по умолчанию используется интерполяция текущего раздела (и, возможно, значений по умолчанию из специального раздела).Например, конфигурация, указанная выше с базовой интерполяцией, будет выглядеть так с расширенной интерполяцией:

   [Paths]
   home_dir: /Users
   my_dir: ${home_dir}/lumberjack
   my_pictures: ${my_dir}/Pictures

Также могут быть получены значения из других секций:

   [Common]
   home_dir: /Users
   library_dir: /Library
   system_dir: /System
   macports_dir: /opt/local

   [Frameworks]
   Python: 3.2
   path: ${Common:system_dir}/Library/Frameworks/

   [Arthur]
   nickname: Two Sheds
   last_name: Jackson
   my_dir: ${Common:home_dir}/twosheds
   my_pictures: ${my_dir}/Pictures
   python_dir: ${Frameworks:path}/Python/Versions/${Frameworks:Python}
2 голосов
/ 01 июля 2015

У вас есть доступ к специальному разделу [ПО УМОЛЧАНИЮ].К определенным здесь значениям можно получить доступ посредством интерполяции из других разделов, даже для более старых версий Python.

0 голосов
/ 08 марта 2016

Я столкнулся с этим в проекте, над которым я сейчас работаю, и я реализовал быстрое расширение класса ConfigParser.SafeConfigParser, в котором я переписал функцию get().Я думал, что некоторые могут найти это полезным.

import re
import ConfigParser

class ExtParser(ConfigParser.SafeConfigParser):
     #implementing extended interpolation
     def __init__(self, *args, **kwargs):
         self.cur_depth = 0 
         ConfigParser.SafeConfigParser.__init__(self, *args, **kwargs)


     def get(self, section, option, raw=False, vars=None):
         r_opt = ConfigParser.SafeConfigParser.get(self, section, option, raw=True, vars=vars)
         if raw:
             return r_opt

         ret = r_opt
         re_oldintp = r'%\((\w*)\)s'
         re_newintp = r'\$\{(\w*):(\w*)\}'

         m_new = re.findall(re_newintp, r_opt)
         if m_new:
             for f_section, f_option in m_new:
                 self.cur_depth = self.cur_depth + 1 
                 if self.cur_depth < ConfigParser.MAX_INTERPOLATION_DEPTH:
                     sub = self.get(f_section, f_option, vars=vars)
                     ret = ret.replace('${{{0}:{1}}}'.format(f_section, f_option), sub)
                 else:
                     raise ConfigParser.InterpolationDepthError, (option, section, r_opt)



         m_old = re.findall(re_oldintp, r_opt)
         if m_old:
             for l_option in m_old:
                 self.cur_depth = self.cur_depth + 1 
                 if self.cur_depth < ConfigParser.MAX_INTERPOLATION_DEPTH:
                     sub = self.get(section, l_option, vars=vars)
                     ret = ret.replace('%({0})s'.format(l_option), sub)
                 else:
                     raise ConfigParser.InterpolationDepthError, (option, section, r_opt)

         self.cur_depth = self.cur_depth - 1 
         return ret 
0 голосов
/ 23 ноября 2014

Если вы застряли в Python 2.7 и вам нужно выполнить интерполяцию по сечениям, это достаточно легко сделать вручную, используя регулярные выражения.

Вот код:

INTERPOLATION_RE = re.compile(r"\$\{(?:(?P<section>[^:]+):)?(?P<key>[^}]+)\}")

def load_something_from_cp(cp, section="section"):
    result = []
    def interpolate_func(match):
        d = match.groupdict()
        section = d.get('section', section)
        key = d.get('key')
        return cp.get(section, key)
    for k, v in cp.items(section):
        v = re.sub(INTERPOLATION_RE, interpolate_func, v)
        result.append(
            (v, k)
        )
    return result

Предостережения:

  • В интерполяции нет рекурсии
  • При разборе многих разделов вам потребуетсякак-то угадать текущий раздел.
...