PythonとJinjaを使った自動生成をもっと手軽に

Python
田中太郎
田中太郎

Pythonで自動生成スクリプトを作りたいけどめんどくさい

という人向けに「自動生成スクリプトを手軽に使えるスクリプト」を紹介します

使い方

必要環境

・Python3

・Jinja2

必要ファイル

・実行ファイル:auto_generate.py

・テンプレート:template.j2

・テキストファイル(1つ以上):data1.txt

・実行コマンド

./auto_generate.py template.j2 data1.txt

使用例

下記のようなエクセルファイルがあるとします。

これをdata1.txtというテキストファイルにコピペします。

また、下記のようなテンプレート(template.j2)があるとします。

そしてコマンドを実行します

./auto_generate.py template.j2 data1.txt

そうするとこんな結果が得られます。

コード

auto_generate.py
import os
import sys

import jinja2


def check_error(file_pathes):
    """エラーチェックをする"""
    for file_path in file_pathes:
        if not os.path.exists(file_path):
            sys.exit("{} is not found".format(file_path))
    if len(file_pathes) <= 2:
        sys.exit("There are not enough arguments")


def create_data(args):
    """テンプレートで使う文字列を作成する"""
    filenames = [os.path.splitext(os.path.basename(arg))[0] for arg in args]
    data = {"{}".format(os.path.splitext(filename)[0]):[] for filename in filenames}
    for arg in args:
        with open(arg, "r") as f:
            data[os.path.splitext(os.path.basename(arg))[0]] = [i.replace("\n", "").split() for i in f]

    return data


def execute_jinja2(j2_path, data):
    """Jinjaのテンプレートを読み込む"""
    j2_dir_path = os.path.dirname(j2_path)
    env = jinja2.Environment(
        loader=jinja2.FileSystemLoader(j2_dir_path),
        trim_blocks=True,
        lstrip_blocks=True,
    )
    template = env.get_template(os.path.basename(j2_path))
    return template.render(data=data)


if __name__ == "__main__":
    check_error(sys.argv)
    result = execute_jinja2(sys.argv[1], create_data(sys.argv[2:]))
    print(result)

コードの解説

def check_error(file_pathes):
    """エラーチェックをする"""
    for file_path in file_pathes:
        if not os.path.exists(file_path):
            sys.exit("{} is not found".format(file_path))
    if len(file_pathes) <= 2:
        sys.exit("There are not enough arguments")

file_pathesで与えたファイルが存在するかチェックします。

ない場合はエラーで終了します。

また、引数が2以下(Jinjaファイルとテキストファイル)でもエラーを出します。

def create_data(args):
    """テンプレートで使う文字列を作成する"""
    filenames = [os.path.splitext(os.path.basename(arg))[0] for arg in args]
    data = {"{}".format(os.path.splitext(filename)[0]):[] for filename in filenames}
    for arg in args:
        with open(arg, "r") as f:
            data[os.path.splitext(os.path.basename(arg))[0]] = [i.replace("\n", "").split() for i in f]

    return data

Jinjaファイルで使うデータを成型します。

成型といっても、引数にしたテキストファイルをキーにした辞書を作成します。

Jinjaファイル内で使う場合はdata[<ファイル名>]のように使えます。

def execute_jinja2(j2_path, data):
    """Jinjaのテンプレートを読み込む"""
    j2_dir_path = os.path.dirname(j2_path)
    env = jinja2.Environment(
        loader=jinja2.FileSystemLoader(j2_dir_path),
        trim_blocks=True,
        lstrip_blocks=True,
    )
    template = env.get_template(os.path.basename(j2_path))
    return template.render(data=data)

Jinjaを使う準備をしています。Jinjaの詳しい使い方はここでは割愛しますが、

上記の関数にJinjaファイルのパスとデータを与えることでテンプレートを作成できます。

if __name__ == "__main__":
    check_error(sys.argv)
    result = execute_jinja2(sys.argv[1], create_data(sys.argv[2:]))
    print(result)
check_error(sys.argv)

実行時に与えた引数が存在するかチェックします。

ない場合はエラーを出して終了します。

result = execute_jinja2(sys.argv[1], create_data(sys.argv[2:]))

sys.argv[0]は実行ファイル自身(ここではauto_generate.py)なので

sys.argv[1]でexecute_jinja2にJinjaファイルを与えています。

create_data(sys.argv[2:])では、Jinjaファイルで使うデータ(data1.txtから取得したデータ)を生成します。

結果をexecute_jinja2に与えます。

まとめ

Jinjaを使った自動生成を手軽にできるスクリプトを作成しました。

ぜひ使ってみて下さい。

コメント

タイトルとURLをコピーしました