モジュールは 、コンテンツがキーと値のペアである(つまり、INIスタイルのセクションヘッダーがない)ConfigParser
単純なJavaスタイルのファイルを解析する場合に例外を発生させます。.properties
いくつかの回避策はありますか?
10 に答える
たとえば、次のようにします。
$ cat my.props
first: primo
second: secondo
third: terzo
つまり.config
、先頭のセクション名がないことを除いて、形式になります。次に、セクション ヘッダーを偽造するのは簡単です。
import ConfigParser
class FakeSecHead(object):
def __init__(self, fp):
self.fp = fp
self.sechead = '[asection]\n'
def readline(self):
if self.sechead:
try:
return self.sechead
finally:
self.sechead = None
else:
return self.fp.readline()
利用方法:
cp = ConfigParser.SafeConfigParser()
cp.readfp(FakeSecHead(open('my.props')))
print cp.items('asection')
出力:
[('second', 'secondo'), ('third', 'terzo'), ('first', 'primo')]
私の解決策はStringIO
、単純なダミーヘッダーを使用して先頭に追加することです:
import StringIO
import os
config = StringIO.StringIO()
config.write('[dummysection]\n')
config.write(open('myrealconfig.ini').read())
config.seek(0, os.SEEK_SET)
import ConfigParser
cp = ConfigParser.ConfigParser()
cp.readfp(config)
somevalue = cp.getint('dummysection', 'somevalue')
上記の Alex Martelli の回答は、Python 3.2 以降では機能しreadfp()
ませread_file()
んreadline()
。
同じアプローチを使用するスニペットを次に示しますが、Python 3.2+ で動作します。
>>> import configparser
>>> def add_section_header(properties_file, header_name):
... # configparser.ConfigParser requires at least one section header in a properties file.
... # Our properties file doesn't have one, so add a header to it on the fly.
... yield '[{}]\n'.format(header_name)
... for line in properties_file:
... yield line
...
>>> file = open('my.props', encoding="utf_8")
>>> config = configparser.ConfigParser()
>>> config.read_file(add_section_header(file, 'asection'), source='my.props')
>>> config['asection']['first']
'primo'
>>> dict(config['asection'])
{'second': 'secondo', 'third': 'terzo', 'first': 'primo'}
>>>
わーい!別のバージョン
この回答に基づいて(追加はdict
、with
ステートメントを使用し、%
文字をサポートしています)
import ConfigParser
import StringIO
import os
def read_properties_file(file_path):
with open(file_path) as f:
config = StringIO.StringIO()
config.write('[dummy_section]\n')
config.write(f.read().replace('%', '%%'))
config.seek(0, os.SEEK_SET)
cp = ConfigParser.SafeConfigParser()
cp.readfp(config)
return dict(cp.items('dummy_section'))
使用法
props = read_properties_file('/tmp/database.properties')
# It will raise if `name` is not in the properties file
name = props['name']
# And if you deal with optional settings, use:
connection_string = props.get('connection-string')
password = props.get('password')
print name, connection_string, password
私の例で使用されている.properties
ファイル
name=mongo
connection-string=mongodb://...
password=my-password%1234
編集 2015-11-06
キャラクターに問題があったと言及したニール・リマに感謝し%
ます。
その理由は、ファイルConfigParser
を解析するように設計されてい.ini
ます。文字は%
特殊な構文です。単純に追加された文字を使用するには、構文に従って%
aa を%
withに置き換えます。%%
.ini
この回答は、Python 3 で itertools.chain を使用することを提案しています。
from configparser import ConfigParser
from itertools import chain
parser = ConfigParser()
with open("foo.conf") as lines:
lines = chain(("[dummysection]",), lines) # This line does the trick.
parser.read_file(lines)
with open('mykeyvaluepairs.properties') as f:
defaults = dict([line.split() for line in f])
config = configparser.ConfigParser(defaults)
config.add_section('dummy_section')
config.get('dummy_section', option)
DEFAULT セクションから 'option' を返すようになりました。
また:
with open('mykeyvaluepairs.properties') as f:
properties = dict([line.split() for line in f])
config = configparser.ConfigParser()
config.add_section('properties')
for prop, val in properties.items():
config.set('properties', prop, val)
その場合config.get('properties', option)
、デフォルトのセクションに頼りません。