Python ConfigParser interpolación de la sección extranjera

Con Python ConfigParser, ¿es posible utilizar la interpolación en secciones extranjeras? Mi mente parece decirme que he visto que es posible en algún lugar, pero no puedo encontrarlo cuando busco.

Este ejemplo no funciona, pero es para dar una idea de lo que estoy tratando de hacer.

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

Tenga en cuenta que estoy usando Python 2.4.

En Python 3.2 y más, esto es perfectamente válido:

 [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} 

Editar:

Acabo de ver que está usando python 2.4 , así que no , la interpolación de sección no se puede hacer en python 2.4 . Se introdujo en Python 3.2 – Consulte la sección 13.2.5 – Interpolación de valores de ConfigParser .

clase configparser.ExtendedInterpolation

Un controlador alternativo para la interpolación que implementa una syntax más avanzada, utilizada por ejemplo en zc.buildout. La interpolación extendida utiliza $ {section: option} para denotar un valor de una sección extranjera. La interpolación puede abarcar múltiples niveles. Por conveniencia, si se omite la sección: parte, la interpolación se establece de manera predeterminada en la sección actual (y posiblemente en los valores predeterminados de la sección especial). Por ejemplo, la configuración especificada anteriormente con interpolación básica, se vería así con la interpolación extendida:

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

Los valores de otras secciones también se pueden obtener:

  [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} 

Tiene acceso a la sección [DEFAULT] de casos especiales. Se puede acceder a los valores definidos aquí mediante la interpolación desde otras secciones, incluso para versiones anteriores de Python.

Si está atascado con Python 2.7 y necesita realizar una interpolación de sección transversal, es bastante fácil hacerlo manualmente utilizando expresiones regulares.

Aquí está el código:

 INTERPOLATION_RE = re.compile(r"\$\{(?:(?P
[^:]+):)?(?P[^}]+)\}") 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

Cuevas

  • No hay recursión en la interpolación.
  • Cuando analice muchas secciones, necesitará adivinar de alguna manera la sección actual.

Me he encontrado con esto en el proyecto en el que estoy trabajando ahora mismo, e implementé una extensión rápida a la clase ConfigParser.SafeConfigParser en la que he sobrescrito la función get() . Pensé que algunos pueden encontrarlo útil.

 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