Python

[Python] ConfigParserでiniファイルからリストを取得したい

ConfigParserでiniファイルからリストを取得したい

PythonのConfigParserを使うと、iniファイルから設定を読み込んで利用することができる。
iniファイルには自由なキーと値を設定できるが、値をリストとして取得したい場合どうすればよいのか。

今回はConfigParserでiniファイルからリストを取得する方法について紹介する。


iniファイルとは

iniファイルとはその名の通り拡張子が ini となっているファイルである。

ファイル形式としては普通のテキストファイルと同じで、メモ帳のようなテキストエディタで読み書きができる。

ではテキストファイルと何が違うのかというと、使われ方に特徴がある。

iniファイルはプログラムの設定ファイルとして使われる。
iniファイルを用いるメリットとしては、プログラム本体と設定ファイルを切り離すことで、本体のコードには変更を加えずに色々な設定でプログラムを動作させることができる。

INIファイルは構造の単純なテキストファイルであり、設定ファイルのフォーマットとしてよく使われている。INIファイルは主にWindowsで使用するが、他のプラットフォームでも使われる。 INIファイルという名前はこのファイルの一般的な拡張子「.INI」から来ている。


iniファイルをPythonから扱う方法

そんなiniファイルをPythonでも扱いたい場合は ConfigParser を用いる。

まずiniファイルのサンプルとして以下のような sample.ini ファイルを用意する。

[settings]
SETTINGS_01=settings content 01
SETTINGS_02=settings content 02

そしてPythonから ConfigParser を用いてiniファイルを読み込むと、iniファイルの各設定を呼び出すことができる。
第1引数が [settings] に対応するセクションを指定しており、第2引数でキー SETTINGS_01 を指定して対応する値を取得している。

import configparser

config = configparser.ConfigParser()
config.read("sample.ini")

settings_01 = config.get("settings", "SETTINGS_01")
settings_02 = config.get("settings", "SETTINGS_02")
print("settings_01: {}".format(settings_01))
print("settings_02: {}".format(settings_02))

# settings_01: settings content 01
# settings_02: settings content 02


iniファイルからリストを取得したい

Pythonからiniファイルを扱う方法はわかった。
しかしここで新たな疑問が出てくる。

iniファイル中のキーに対応する値としてリストを設定して、Pythonから値を取得する際にlist型として取得できないか。

試してみると以下のようになる。

[settings_list]
SETTINGS_03=["content03-1","content03-2","content03-3"]
settings_03 = config.get("settings_list", "SETTINGS_03")
print(settings_03)
print(type(settings_03))

# ["content03-1","content03-2","content03-3"]
# <class 'str'>

複数要素で構成されたlist型で取得したいが、実際に取得できたのは全ての要素が1つの文字列としてつながったstr型。

つまりiniファイルから取得した要素は文字列としてPythonに読み込まれる。

では設定をリストとして持たせて取り込むのは不可能かというと、そうでもない。


evalで取り込む

文字列をコードとして評価する eval() を使うと [] で括られたlist型としてデータを取得することができる。

settings_03_1 = eval(config.get("settings_list", "SETTINGS_03"))
print(settings_03_1)
print(type(settings_03_1))

# ['content03-1', 'content03-2', 'content03-3']
# <class 'list'>

しかし eval() は任意の内容をコードとして評価する為、プログラム製作者の意図から逸脱した悪意あるコードをiniに仕込まれた場合、実行されてしまうという脆弱性をもっている。

なので別の方法も考えてみる。


リストはiniファイルの外の用意して読み込む

設定ファイルのメリットはプログラム本体とは別ファイルとして扱えること。
ではリスト形式の設定を必ずしもiniファイルに持つ必要はない。
リスト形式の設定は csv から読み込めばいい。

やり方としては、iniファイルにはリスト設定を書き込んだcsvファイルのパスを書いておく。

[settings_list]
SETTINGS_03_CSV=SETTINGS_03.csv

そしてリスト設定を書き込んだcsvファイル SETTINGS_03.csv をiniファイルとは別で用意する。

CONTENT
content03-1
content03-2
content03-3

そしてPython側ではiniファイルから読み込んだcsvファイルのパスを、pd.read_csv() で読み込んでしまえばDataFrameもしくはlist型として設定を読み込むことができる。

import pandas as pd

settings_03_csv = config.get("settings_list", "SETTINGS_03_CSV")
print(settings_03_csv)

df_settings_03 = pd.read_csv(settings_03_csv)
print(df_settings_03["CONTENT"].to_list())
print(type(df_settings_03["CONTENT"].to_list()))

# ['content03-1', 'content03-2', 'content03-3']
# <class 'list'>

この方法であれば eval() のように任意のコードを仕込まれる心配は無い。


jsonで読み込む

また eval() の代わりにjsonライブラリの json.loads() を使って読み込むことも可能。

import json

settings_03_1 = json.loads(config.get("settings_list", "SETTINGS_03"))
print(settings_03_1)
print(type(settings_03_1))

# ['content03-1', 'content03-2', 'content03-3']
# <class 'list'>


まとめ

ConfigParserでiniファイルからリストを取得したい場合は、 eval() を利用することでlist型として読み込むこともできるが脆弱性のリスクがある。

eval() の代わりにjsonライブラリの json.loads() を使うか、リストをcsvとして外出しにしてcsvのパスをiniファイルに持たせるかすると良い。

コード


KRSW

駆け出し機械学習エンジニア。機械学習、DB、WEBと浅く広い感じ。 Junior machine learning engineer. Not a specialist but a generalist who knows DB, WEB too.

役に立ったらシェアしてくれると励みになります。
If you felt this article is useful, please share.
にほんブログ村 IT技術ブログへ

-Python

Translate »
Social media & sharing icons powered by UltimatelySocial

Copyright© ITips , 2020 All Rights Reserved.