ConfigParser与环境变量的字符串插值
我对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
编辑:
我原以为$
这种语法是自动包含在所谓的字符串插值中的(可以参考手册):
在核心功能的基础上,SafeConfigParser支持插值。这意味着值可以包含格式字符串,这些字符串可以引用同一部分中的其他值,或者引用一个特殊的DEFAULT部分中的值。
但我错了。那我该怎么处理这种情况呢?
9 个回答
3
根据@alex-markov的回答(和代码)以及@srand9的评论,下面的解决方案可以使用环境变量和交叉引用。
请注意,现在的插值是基于ExtendedInterpolation
,这样可以支持交叉引用,并且使用的是before_read
,而不是before_get
。
#!/usr/bin/env python3
import configparser
import os
class EnvInterpolation(configparser.ExtendedInterpolation):
"""Interpolation which expands environment variables in values."""
def before_read(self, parser, section, option, value):
value = super().before_read(parser, section, option, value)
return os.path.expandvars(value)
cfg = """
[paths]
foo : ${HOME}
[section1]
key = value
my_path = ${paths:foo}/path
"""
config = configparser.ConfigParser(interpolation=EnvInterpolation())
config.read_string(cfg)
print(config['section1']['my_path'])
3
要正确地从环境中替换变量,诀窍是使用 ${} 这种语法来表示环境变量:
[DEFAULT]
test_home=${HOME}
[test]
test_1=%(test_home)s/foo.csv
test_2=%(test_home)s/bar.csv
3
如果你想展开一些环境变量,可以在解析 StringIO
流之前,使用 os.path.expandvars
来实现:
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))
13
如果你使用的是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):
value = super().before_get(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'])
42
首先,根据文档的说明,你应该使用 %(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