Python ConfigParser 从外部部分插值

发布于 2024-12-07 04:52:26 字数 290 浏览 5 评论 0原文

使用Python ConfigParser,是否可以跨外部部分使用插值?我的大脑似乎告诉我,我在某个地方看到了它的可能,但在搜索时我找不到它。

这个例子不起作用,但它可以让我了解我正在尝试做什么。

[section1]
root = /usr

[section2]
root = /usr/local

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

请注意,我使用的是 Python 2.4。

With Python ConfigParser, is it possible to use interpolation across foreign sections? My mind seems to tell me I've seen that it's possible somewhere, but I can't find it when searching.

This example doesn't work, but it's to give an idea of what I'm trying to do.

[section1]
root = /usr

[section2]
root = /usr/local

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

Note that I'm using Python 2.4.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

·深蓝 2024-12-14 04:52:26

在 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 值插值

configparser.ExtendedInterpolation

替代处理程序
用于实现更高级语法的插值,用于
zc.buildout 中的实例。扩展插值正在使用
${section:option} 表示来自外部部分的值。
插值可以跨越多个级别。为了方便起见,如果
section:省略部分,插值默认为当前
部分(可能还有特殊部分的默认值)。
例如,上面指定的基本配置
插值,使用扩展插值看起来像这样:

<前><代码> [路径]
home_dir:/用户
my_dir: ${home_dir}/伐木工人
my_pictures:${my_dir}/图片

也可以获取其他部分的值:

<前><代码> [常用]
home_dir:/用户
库目录:/库
系统目录:/系统
macports_dir:/opt/local

[框架]
蟒蛇:3.2
路径:${Common:system_dir}/Library/Frameworks/

[亚瑟]
昵称: 两个棚子
姓氏:杰克逊
my_dir: ${Common:home_dir}/twosheds
my_pictures:${my_dir}/图片
python_dir: ${框架:路径}/Python/版本/${框架:Python}

In python 3.2 and up this is perfectly valid:

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

Edit:

I just saw that you are using python 2.4, so no, section interpolation cannot be done in python 2.4. It was introduced in python 3.2 - See section 13.2.5 - ConfigParser Interpolation of values.

class configparser.ExtendedInterpolation

An alternative handler
for interpolation which implements a more advanced syntax, used for
instance in zc.buildout. Extended interpolation is using
${section:option} to denote a value from a foreign section.
Interpolation can span multiple levels. For convenience, if the
section: part is omitted, interpolation defaults to the current
section (and possibly the default values from the special section).
For example, the configuration specified above with basic
interpolation, would look like this with extended interpolation:

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

Values from other sections can be fetched as well:

   [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}
夜夜流光相皎洁 2024-12-14 04:52:26

您确实可以访问特殊情况的 [DEFAULT] 部分。即使对于旧版本的 Python,也可以通过其他部分的插值来访问此处定义的值。

You do have access to the special-case [DEFAULT] section. Values defined here can be accessed via interpolation from other sections even for older versions of Python.

守望孤独 2024-12-14 04:52:26

如果您坚持使用 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

注意事项:

  • 插值中没有递归
  • 当解析许多部分时,您需要以某种方式猜测当前部分。

If you're stuck with python 2.7 and you need to do cross-section interpolation it is easy enough to do this by hand using regexps.

Here is the code:

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

Caveeats:

  • There is no recursion in interpolation
  • When parsing many sections, youll need to somehow guess current section.
三生殊途 2024-12-14 04:52:26

我在我现在正在处理的项目中遇到了这个问题,我实现了对 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 

I have run into this in the project I'm working on right now, and I implemented a quick extension to the ConfigParser.SafeConfigParser class in which I have overwritten the get() function. I thought some may find it useful.

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 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文