它有点我没有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
我认为$
语法隐含地包含在所谓的字符串插值中(指的是manual):
除了核心功能之外,SafeConfigParser还支持插值。这意味着值可以包含引用同一节中其他值的格式字符串,或特殊DEFAULT节中的值。
但我错了。如何处理这种情况?
首先根据文档,您应该使用%(test_home)s
来插入test_home
。此外,密钥不区分大小写,您不能同时使用HOME
和home
密钥。最后,您可以使用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
您可以在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'])
如果要扩展某些环境变量,可以在解析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))
即使您将值设置为整数或True,ConfigParser.get值也是字符串。但ConfigParser有getint,getfloat和getboolean。
的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的回答。
从环境中进行适当变量替换的技巧是使用$ {}语法来表示环境变量:
[DEFAULT]
test_home=${HOME}
[test]
test_1=%(test_home)s/foo.csv
test_2=%(test_home)s/bar.csv
似乎在最后一个版本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,))
BasicInterpolation
和EnvInterpolation
之间的区别在于:
v = os.environ.get(var.upper())
if v is None:
v = map[var]
在检查qazxsw poi之前,我正试图在环境中找到qazxsw poi。
很晚,但也许它可以帮助其他人寻找我最近的答案。此外,其中一条评论是如何从其他部分获取环境变量和值。以下是我在从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()