本連載を熱心に読んでいる皆さんであれば、自作ツールを作成して業務で活用しているのではないだろうか。それで自作ツールに設定項目がある場合、どのように指定しているだろうか。今回は、メジャーなアプリの設定ファイルについて調べたり、Pythonでどのように扱ったら良いのかを紹介する。残念ながら2020年の東京オリンピックは延期になってしまったが、ここに設定ファイル選手権の開催を宣言する。
オープンソースのアプリはどんな形式の設定ファイル?
業務で大勢の人が使うツールでは、設定がGUIで直感的に行えるようになっている。とは言え、GUIで指定した設定自体も、何かしらの設定ファイルに保存される。一昔前のツールであれば、バイナリの独自形式で保存されることも多かったが、昨今のツールの多くは、XMLやJSONなど有名なデータフォーマットを採用していることが多い。また、拡張子こそ独自のものだったりするが、テキストエディタやバイナリで開いて中を見たらXMLやJSONだったという場合も多い。
なお、有名なオープンソースのソフトウェアがどのような設定ファイルを採用しているのかを研究してみるのも一興だ。最近勢いのある、テキストエディタのATOMエディタの設定ファイルはJSON形式を採用している。プログラミングエディタのVisual Studio CodeもJSONを採用している。
そして、WebブラウザのGoogle Chromeのブックマークのデータを開いてみると、やはりJSON形式だった。そして、サイトのクッキーデータを保存するデータファイルを調べて見るとSQLite形式のデータベースだった。SQLiteはオープンな組み込みデータベースで広く普及している。コマンドラインからも操作が容易で、Pythonをはじめ多くのプログラミング言語から手軽に操作できる形式だ。また、同じくブラウザのFirefoxの設定フォルダを開いてみると、同じく、たくさんのJSON形式のファイルやSQLite形式のデータベースファイルがあった。そして、古くからWindowsアプリの設定ファイルとして利用されているINIファイルも見つかった。
このように、最近のツールやアプリの設定ファイルは圧倒的にJSON形式のファイルが多い。一昔前だとXMLが多かったが最近では圧倒的にJSON形式が増えている。JSON形式はオープンな規格であり、各プログラミング言語が読み書きをサポートしていること、また、形式もシンプルでありながら、複雑な構造のデータを表現できるのが良いところだ。
自作ツールの設定ファイルはどの形式が良いのか?
実際のところ、自作ツールは自分のためのツールであることが多いので、自分のモチベーションが上がる形式であればどんなものでも良いだろう。どんな形式を採用したとしても誰も文句を言う人はいない。とは言え、多くの人が利用している一般的なデータ形式を選ぶならメリットが多くある。将来的に別のツールにインポートしたり、データ形式を変換したりといった操作が容易になる。
それでは、これからいくつか設定ファイルの候補となる形式をいくつか紹介していこう。
【ソースコードに設定データをベタ書き】
なお、大した設定がない場合は、別に設定ファイルを作るまでもなく、ソースコードにベタ書きすることもできる。Pythonを使うのであれば、Pythonのデータ型(リストや辞書型)を使って記述することができる。これは、ある意味、ソースコード自体がデータファイルになっていると言える。そもそも、ここまで様々なツールで設定ファイルとして利用されているJSON形式も、JavaScriptのObject/Array型を手軽に記述するオブジェクトリテラルから取られたデータ形式だ。
そのため、自分ツールであるならば、ソースコードが設定データというのも悪くはない選択だ。データの読み込み時間も不要だし、何より読み込みを行う処理を記述する必要が全くない。例えば、ユーザー情報(名前やURL)を設定ファイルに保存して、Pythonのプログラムから読み込んでみよう。
まずは、以下の設定データを「mydata.py」というファイルで保存した。拡張子から分かるように、Pythonのプログラムファイルで、辞書型のデータを記述したものだ。
# file: mydata.py
# 以下ユーザー情報を記述
user_info = {
"name": "kujira",
"password": "hoge",
"email": "web@kujirahand.com",
"url": "https://kujirahand.com"
}
このデータファイルを利用するメインプログラムは以下のようになる。データの内容を読むのに何の工夫も要らない。上記の設定ファイルをPythonのモジュールとして利用するだけ。読み込みのためのコードは冒頭の一行「import mydata」と書くのみだ。
# file: read_mydata.py
import mydata
# データを表示する
info = mydata.user_info
print(info["name"])
print(info["url"])
データにコメントも書いておけるため、非常に使い勝手が良い。使い勝手としてはダントツに一位なのだが問題もある。その理由だが、純粋なデータではなくプログラムであるため、設定ファイルに他のデータを壊すような処理を埋め込むことができてしまうという点だ。つまり、設定ファイルに悪意のあるコードを埋め込むことができてしまう。また、設定ファイルに記述ミスがあるとプログラム自体が動かなくなるので問題の特定が難しくなる。そのため、自分用のツールであれば問題はないが、多くの人が利用する場合には採用が難しい形式とも言える。
なお、JavaScriptなども、JSON形式のデータファイルをeval()を用いて評価すればデータをパースできるのだが、この方法は推奨されず、JSON.parse/stringifyという専用の読み書き命令が用意されている。
それでも、上記のプログラムを見て分かる通り、非常に簡潔に設定情報を取り込むことができるため自分用のツールと割り切ってしまうなら、悪くない選択と言えよう。
【Pickle】
なお、Pythonネイティブのデータ型を素直にファイルに保存する専用ライブラリもある。それがpickleだ。このライブラリを使うと、辞書型やリスト型は当然として、classオブジェクトをも保存することができる。
ただし、pickleのマニュアルを見ると、安全性の問題があるので、信頼できるデータのみ読み込むようにとの注意書きがある。これは、先ほどのPythonファイルの設定ファイルを使う場合と同じ問題であるが、何でも保存できて便利だが利用には注意が必要ということだ。なお、pickleのマニュアルには、JSON形式を使うことを推奨すると書かれている。
以下は、簡単にpickleを用いて読み書きを行う方法だ。
import pickle
# データの保存先
config_file = "myconfig.pickle"
# 設定データ --- (*1)
config_data = {
"username": "hoge",
"url": "https://kujirahand.com"}
# 設定をファイルに保存 --- (*2)
with open(config_file, "wb") as f:
pickle.dump(config_data, f)
# 保存したファイルを読み込む --- (*3)
with open(config_file, "rb") as f:
tmp = pickle.load(f)
print(tmp["username"])
print(tmp["url"])
簡単に解説しよう。(*1)では保存したい設定データを辞書型で宣言した。(*2)の部分でこれをファイルに保存する。open関数でファイルを書き込みバイナリモード(wb)で開き、pickle.dumpでファイルに保存する。(*3)の部分では設定ファイルを読み込む。書き込みと同じくopen関数を使って読み込みバイナリモード(rb)で開き、pickle.loadでファイルを読み込む。
このように、pickleは、Pythonのデータ型をそのまま読み書きできるのが魅力だが、セキュリティ的には推奨されないとのことなので注意して使おう。
【JSON】
そして、本命の設定ファイル形式がJSON形式だ。JOSN形式では、文字列型・数値型・真偽型(boolean)、null型、配列型、キーと値のペアを表現するObject型を扱うことができる。JSON形式に関して詳しい仕様が、json.orgにまとめられている。
Pythonから扱うには、最初から入っている標準ライブラリの「json」を利用することで、手軽に読み書きを行うことができる。
使い方だが、先ほどのpickleとほとんど同じ要領で使える。以下はJSONファイルを読み書きする例だ。
import json
# データの保存先
config_file = "myconfig.json"
# 設定データ --- (*1)
config_data = {
"username": "hoge",
"url": "https://kujirahand.com"}
# 設定をファイルに保存 --- (*2)
with open(config_file, "w") as f:
json.dump(config_data, f)
# 保存したファイルを読み込む --- (*3)
with open(config_file, "r") as f:
tmp = json.load(f)
print(tmp["username"])
print(tmp["url"])
こちらも簡単に解説しよう。(*1)では保存したい設定データを辞書型で宣言した。(*2)の部分でこれをファイルに保存する。open関数でファイルを書き込みモード(w)で開き、json.dumpでファイルに保存する。(*3)の部分では設定ファイルを読み込む。open関数を使って読み込みモード(r)で開き、json.loadでファイルを読み込む。
このように、json.dumpでファイルを保存、json.loadでファイルを読み込める。JSONの特徴的なデータ型であるオブジェクト(Object)はPythonの辞書型、配列(Array)はPythonのリスト型にマッピングされる。そのため、特にデータ型の変換を意識することなく利用できる。なお、複雑なデータ構造を表現できる上に他の形式と比べて性能も悪くない。
【他の形式】
他にも、設定ファイルの候補となる主要な形式がいくつかあるが、Pythonは豊富なライブラリが魅力なだけあって、様々なデータフォーマットを扱うライブラリが用意されている。
XML形式のデータを扱うなら、xml.etree.ElementTreeライブラリが使える。INIファイル形式でデータを読み書きするなら、configparserライブラリが利用できる。また、CSVファイルなら、csvライブラリやpandasが利用できる。加えて、pandasを使えば、Excelで作成した設定データを読むこともできる。
ちなみに、他の設定ファイルに比べると若干効率は悪いが、敢えてExcel文書を設定ファイルにすることもできる。Excelを使うなら手軽に設定ファイルの値を変更することができからだ。Excelなら入力値の型を強制したり、選択候補を指定することもできるのが良いところだ。GUIによる値設定が必要だが、面倒で設定画面を作りたくない場合には有効な選択肢と言える。
結果発表
以上、簡単に設定ファイルの保存形式について比較してみた。ここまで見てきたように、2020年の『設定ファイル選手権』の覇者は明らかにJSON形式だ。多くの有名なプロジェクトで採用されている実績がある上に、Pythonのマニュアルにも繰り返し、JSON形式を使うようにと指示がある。複雑なデータ構造を表現できる上に可読性も高い。
もちろん、他の形式で紹介したように、PythonならXML、CSV、INI、Excel形式などなど、どんな形式でも手軽に読み書きできる。自作ツールが利用したいデータ形式に則したものを選ぶと良いだろう。
自由型プログラマー。くじらはんどにて、プログラミングの楽しさを伝える活動をしている。代表作に、日本語プログラミング言語「なでしこ」 、テキスト音楽「サクラ」など。2001年オンラインソフト大賞入賞、2004年度未踏ユース スーパークリエータ認定、2010年 OSS貢献者章受賞。技術書も多く執筆している。