使用env变量进行ConfigParser和String插值

问题描述 投票:10回答:7

它有点我没有python语法,我在读取带插值的.ini文件时遇到问题。

这是我的ini文件:

[DEFAULT]
home=$HOME
test_home=$home

[test]
test_1=$test_home/foo.csv
test_2=$test_home/bar.csv

那些台词

from ConfigParser import SafeConfigParser

parser = SafeConfigParser()
parser.read('config.ini')

print parser.get('test', 'test_1')

输出

$test_home/foo.csv

虽然我在期待

/Users/nkint/foo.csv

EDIT:

我认为$语法隐含地包含在所谓的字符串插值中(指的是manual):

除了核心功能之外,SafeConfigParser还支持插值。这意味着值可以包含引用同一节中其他值的格式字符串,或特殊DEFAULT节中的值。

但我错了。如何处理这种情况?

python configparser
7个回答
21
投票

首先根据文档,您应该使用%(test_home)s来插入test_home。此外,密钥不区分大小写,您不能同时使用HOMEhome密钥。最后,您可以使用SafeConfigParser(os.environ)来考虑您的环境。

from ConfigParser import SafeConfigParser
import os


parser = SafeConfigParser(os.environ)
parser.read('config.ini')

config.ini在哪里

[DEFAULT]
test_home=%(HOME)s

[test]
test_1=%(test_home)s/foo.csv
test_2=%(test_home)s/bar.csv

5
投票

您可以在Python 3的情况下编写自定义插值:

import configparser
import os


class EnvInterpolation(configparser.BasicInterpolation):
    """Interpolation which expands environment variables in values."""

    def before_get(self, parser, section, option, value, defaults):
        return os.path.expandvars(value)


cfg = """
[section1]
key = value
my_path = $PATH
"""

config = configparser.ConfigParser(interpolation=EnvInterpolation())
config.read_string(cfg)
print(config['section1']['my_path'])

3
投票

如果要扩展某些环境变量,可以在解析os.path.expandvars流之前使用StringIO执行此操作:

import ConfigParser
import os
import StringIO

with open('config.ini', 'r') as cfg_file:
    cfg_txt = os.path.expandvars(cfg_file.read())

config = ConfigParser.ConfigParser()
config.readfp(StringIO.StringIO(cfg_txt))

1
投票

即使您将值设置为整数或True,ConfigParser.get值也是字符串。但ConfigParser有getintgetfloatgetboolean

的Settings.ini

[default]
home=/home/user/app
tmp=%(home)s/tmp
log=%(home)s/log
sleep=10
debug=True

配置阅读器

>>> from ConfigParser import SafeConfigParser
>>> parser = SafeConfigParser()
>>> parser.read('/home/user/app/settings.ini')
>>> parser.get('defauts', 'home')
'/home/user/app'
>>> parser.get('defauts', 'tmp')
'/home/user/app/tmp'
>>> parser.getint('defauts', 'sleep')
10
>>> parser.getboolean('defauts', 'debug')
True

编辑

事实上,如果用SafeConfigParser初始化os.environ,你可以得到名称值为environ var。感谢Michele's的回答。


1
投票

从环境中进行适当变量替换的技巧是使用$ {}语法来表示环境变量:

[DEFAULT]
test_home=${HOME}

[test]
test_1=%(test_home)s/foo.csv
test_2=%(test_home)s/bar.csv

0
投票

似乎在最后一个版本3.5.0中,ConfigParser没有读取env变量,所以我最终提供了基于BasicInterpolation的自定义插值。

class EnvInterpolation(BasicInterpolation):
    """Interpolation as implemented in the classic ConfigParser,
    plus it checks if the variable is provided as an environment one in uppercase.
    """

    def _interpolate_some(self, parser, option, accum, rest, section, map,
                          depth):
        rawval = parser.get(section, option, raw=True, fallback=rest)
        if depth > MAX_INTERPOLATION_DEPTH:
            raise InterpolationDepthError(option, section, rawval)
        while rest:
            p = rest.find("%")
            if p < 0:
                accum.append(rest)
                return
            if p > 0:
                accum.append(rest[:p])
                rest = rest[p:]
            # p is no longer used
            c = rest[1:2]
            if c == "%":
                accum.append("%")
                rest = rest[2:]
            elif c == "(":
                m = self._KEYCRE.match(rest)
                if m is None:
                    raise InterpolationSyntaxError(option, section,
                                                   "bad interpolation variable reference %r" % rest)
                var = parser.optionxform(m.group(1))
                rest = rest[m.end():]
                try:
                    v = os.environ.get(var.upper())
                    if v is None:
                        v = map[var]
                except KeyError:
                    raise InterpolationMissingOptionError(option, section, rawval, var) from None
                if "%" in v:
                    self._interpolate_some(parser, option, accum, v,
                                           section, map, depth + 1)
                else:
                    accum.append(v)
            else:
                raise InterpolationSyntaxError(
                    option, section,
                    "'%%' must be followed by '%%' or '(', "
                    "found: %r" % (rest,))

BasicInterpolationEnvInterpolation之间的区别在于:

   v = os.environ.get(var.upper())
   if v is None:
       v = map[var]

在检查qazxsw poi之前,我正试图在环境中找到qazxsw poi。


0
投票

很晚,但也许它可以帮助其他人寻找我最近的答案。此外,其中一条评论是如何从其他部分获取环境变量和值。以下是我在从INI文件读入时处理转换环境变量和多节标记的方法。

这个文件:

var

使用ExtendedInterpolation的Python类,以便您可以使用map类型格式。当我使用内置的[PKG] # <VARIABLE_NAME>=<VAR/PATH> PKG_TAG = Q1_RC1 [DELIVERY_DIRS] # <DIR_VARIABLE>=<PATH> NEW_DELIVERY_DIR=${DEL_PATH}\ProjectName_${PKG:PKG_TAG}_DELIVERY 函数(例如上面的${PKG:PKG_TAG})将INI读入字符串时,我添加了转换windows环境变量的功能。

os.path.expandvars()
© www.soinside.com 2019 - 2024. All rights reserved.