ConfigParserでiniファイルからリストを取得したい。
PythonのConfigParserを使うと、iniファイルから設定を読み込んで利用することができる。
iniファイルには自由なキーと値を設定できるが、値をリストとして取得したい場合どうすればよいのか。
今回はConfigParserでiniファイルからリストを取得する方法について紹介する。
この記事を書いている人
記事を読むメリット
Pythonの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ファイルに持たせるかすると良い。
Pythonのコードが出来上がったら次は定期的に実行させる環境に移してコードを実行すると思う。
ランニングコストをかけてネット上に実行環境を作るのもありだが、小型PCを購入してランニングコストを下げるのも1つの手かと思われる。
小型PCの魅力とオススメの機種について書いた記事があるので、もしよければ参考にして欲しい。
あわせて読みたい