Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

ExcelとPythonによる社会インフラシステムの設定ファイルの自動生成

1,315 views

Published on

社会インフラシステムは、仕向け毎に仕様の一部が異なることが多く、仕様の差異を多数の設定パラメータとして管理することがある。このような設定パラメータはしばしば Excel を用いてドキュメント化され、同時に、マクロとして実装されたツールにより、アプリケーションが解釈可能な設定ファイルの生成が行われている。しかしながら、このようなツールにはソースコードとしてのマクロの構成管理の難しさや、継続的インテグレーション(CI)を実現するツールからの実行が困難などの課題がある。

そこで、我々はある社会インフラシステムの向けに、Excel で管理された設定データをもとに、設定ファイルを生成するツールを Python で開発した。本発表では、ツールの開発で得られた以下の知見について述べる。


(1) Embeddable 版 Python のバンドル
-----------------------------------------------

社会インフラシステムのライフサイクルは10年以上にわたるため、長期間ツールも実行可能である必要がある。一方で、ソースコードと使用するライブラリを記述した requirements.txt を共有し、それぞれの環境で pip でパッケージをインストールする方法では、必要なパッケージがリポジトリに存在し続ける保証はなく、同じ環境を再現できなくなる可能性がある。そこで、Embeddable 版の Python をベースに必要なライブラリを追加した Python 実行環境を作成し、ツールとバンドルして利用者間で共有する方法を採用した。


(2) openpyxl による Excel ファイルの読み込みとデータクラスへの変換
---------------------------------------------------------------------

Python から Excel データを読み込む方法はいくつかあるが、本ツール openpyxl を採用した。openpyxl は Excel 2010 以降のドキュメントを読み書きできるライブラリである。openpyxl は Excel ファイルを直接読み込むことができるため、Excel がインストールされていないコンテナ上でも動作し、CI 環境を容易に構築できる。

また、Excel ファイルのテーブルの行を Python 3.7 から導入されたデータクラスのオブジェクトとして読み込めるようにした。Excel 上に記載した独自形式のスキーマ情報をもとにデータクラスを動的に生成することで実現している。


(3) Jinja2 による設定ファイルの生成
-----------------------------------------------

対象としたシステムの中には、設定ファイルの全体ではなく、一部のみを自動生成する必要のあるものがあった。このような設定ファイルの生成には、Web アプリケーションで使用されるテンプレートエンジンンの Jinja2 を使用した。これにより、手作業で編集する部分については、Jinja2 テンプレートを編集することで従来通りの方法を維持しつつ、一部のみを自動生成できる。

Published in: Technology
  • Be the first to comment

ExcelとPythonによる社会インフラシステムの設定ファイルの自動生成

  1. 1. © 2019 Toshiba Corporation 株式会社東芝 ソフトウェア技術センター 武山 文信 2019.9.16 Excel と Python による 社会インフラシステムの 設定ファイルの自動生成 PyCon JP 2019
  2. 2. 2© 2019 Toshiba Corporation • 名前: 武山 文信 • 所属: (株) 東芝 ソフトウェア技術センター • 東芝グループ内のソフトウェア開発部門の困りごとを解決 • ここ数年の私の仕事の傾向: 「製品コードを変えずに、開発効率を上げたい」 • Python 開発歴 2年弱 • 歴史的経緯や、細かいことはあまり知りません… ご容赦ください • 他の言語: C/C++, Java, Ruby, (VBA), … 自己紹介 他の言語が使えれば Python は難しくない!?
  3. 3. 3© 2019 Toshiba Corporation 背景 Python 製ツールの配布 Excel ファイルの読み込み 設定ファイルの生成 おわりに Contents 01 02 03 04 05
  4. 4. 4© 2019 Toshiba Corporation 01 背景
  5. 5. 5© 2019 Toshiba Corporation 東芝グループの製品のほとんどが社会インフラシステム • 電力、送変電・配電 • ビル、オフィス、店舗 • 産業システム • 公共、交通、放送 特徴: 設定がとても多い(傾向にある) • お客様ごとに仕様が少しずつ変えた製品を開発 • 製品ごとの仕様の差異を設定として吸収 • 機器構成の違い • 部分的な動作の違い • … 社会インフラシステムのソフトウェア
  6. 6. 6© 2019 Toshiba Corporation Q1. 社会インフラシステム関連のソフトウェアの開発を している方はいらっしゃいますか? Q2. Excel 好きですか?使っていますか? VBA 好きですか? 会場の皆さんに質問です
  7. 7. 7© 2019 Toshiba Corporation Excel で管理することがしばしば 大量の設定データの管理 背景 • 作成者: ソフトウェア開発者、企画担当者、ハードウェア設計者 • 既にコミュニケーションツールになっている 利点 • 強力な表現力(数式など) • 編集機能(オートフィルなど) • そのまま印刷できる 事業領域により異なる
  8. 8. 8© 2019 Toshiba Corporation ツールでアプリケーションが読む設定ファイルを生成する これまでの工夫: 設定ファイルの自動生成 生成ツール ini xml アプリケーションが読み込む 設定ファイル Excel で管理された設定データ 設定の量が膨大な場合でも、ドキュメントに沿った設定ファイルを作成可 アプリケーションは読めない
  9. 9. 9© 2019 Toshiba Corporation Visual Basic for Application (VBA) で開発してきたため、 どうしても制限が多い 従来のツールの課題 1. ツールのソースコードの構成管理が難しい 最新版のソースコードがどの Excel ファイルに含まれているか 分からなくなる 2. 継続的インテグレーション(CI)に組み込みにくい Excel が動くコンテナを作る!? 3. … 本格的な開発ツールではない
  10. 10. 10© 2019 Toshiba Corporation Python で Excel のデータをもとに設定ファイルを生成 そうだ Python にしよう! システムA システムB システムC システム A ドキュメントから Ansible 向けの設定ファイルの生成 システム B 設定ファイル生成ツール新規作成し、手作業の自動化 システム C 既存の VBA のツールの作り直し 2019年2018年 同じ領域の3種類のシステム向けにツールを開発 新規・作り直し両方あり VBA で YAML を 生成したくない! システムB これは良い! Excel の設定項目の 追加のしやすさも重要 CI! ツール・プロセスの 問題分析
  11. 11. 11© 2019 Toshiba Corporation 検討の観点 中長期的に製品開発部門でメンテナンスしやすいか? なぜ Python なのか? 書籍やオンラインの情報が充実 開発に必要な情報が多い ライブラリや開発ツールが充実 Python 人口の多さ・拡大 Python をマクロ言語として 採用する流れがある YAML, IP アドレスの計算、… VS Code, PyCharm, … 情報系出身の新卒エンジニアで あれば、使える可能性が高い (VBA の経験は期待できない) Excel が Python をマクロ言語 として採用するかもしれないこ とで盛り上がった(※当時) 1 2 3 4
  12. 12. 12© 2019 Toshiba Corporation 利用者 • 設定データの作成関係者は幅広い • ツールの利用者はソフトウェア開発者が中心 ツールの構造 • データとツールは分離したい • Windows と Linux で実行したい 入力(Excel) • データの種類: 数値(10進数・16進数)、文字列、IP アドレス… • アプリケーション固有・共通のデータがあり、 複数のファイルに分けられる • 入力用シートの見た目の変更に強い 出力ファイル • 既存の設定ファイルのフォーマットは変えられない • 部分的な自動化を行える 設定ファイル生成ツールに求められる条件の整理 構成管理や実行以外にも、 ツールの一部の数式を壊されたり
  13. 13. 13© 2019 Toshiba Corporation Python による設定ファイルを生成ツールの開発で得られた テクニックを紹介 以降の流れ Python 製ツールの配布 ライブラリを追加した Embeddable 版 Python をツールにバンドル Excel ファイルの読み込み openpyxl による Excel ファイル読み込みと、 スキーマをもとにしたクラス生成・そのオブジェクトへの変換 設定ファイルの生成 テンプレートエンジン Jinja2 の活用
  14. 14. 14© 2019 Toshiba Corporation 02 Python 製ツールの配布
  15. 15. 15© 2019 Toshiba Corporation 課題 Python実行環境 ユーザー間は開発者で、配布範囲は狭いが、 同じバージョンに統一できるか? ライブラリ 社会インフラシステムはライフサイクルが長いので、 10年、20年先もインストールできるか? ツールの配布 VBA のツールは、設定データと一緒に配り実行できた Python の場合 ツール本体 + Python 実行環境 + ライブラリ が必要 pip では難しい? Python 3.7.4 Python 3.6.5
  16. 16. 16© 2019 Toshiba Corporation ツールのソースコードと Python 実行環境をセットで配布 今回の手段 アプリケーション組み込み用の Embeddable 版に ライブラリを事前にインストール 別のアプローチ: pyinstaller [1] による exe 化 実行用の exe ファイルを生成し、実行環境・ライブラリをまとめて配布できる VBA のようにコードを編集できるよう現方式を採用 https://www.python.org/downloads/rel ease/python-374/ Embeddable 版 いつものダウンロード ページから入手可能 [1] https://www.pyinstaller.org/
  17. 17. 17© 2019 Toshiba Corporation 1. pip の –t オプションで指定ディレクトリにインストール 2. インストールしたディレクトリを zip ファイルで圧縮する • zip ファイル内に packages ディレクトリを 作らないように注意 Embeddable 版へのライブラリのインストール 1/2 pip --disable-pip-version-check ¥ install -t packages/ --no-compile -r requirements.txt • Embeddable 版の Python では pip を実行できないので、通常の Python を使用 • --no-compile: pyc ファイルにインストールした環境の絶対パスが埋め込まれるので、 ソースのみインストール
  18. 18. 18© 2019 Toshiba Corporation 3. インストールしたライブラリ(zipファイル)とツールを パスに追加 Embeddable 版へのライブラリのインストール 2/2 python37.zip packages.zip . ../ # Uncomment to run site.main() automatically #import site python37._pth: Embeddable 版の一部 設定ファイル自動生成ツール ├─run.bat ├─configtool │ └─ __main__.py └─python ├─ python.exe : : ├─ python37._pth └─ packages.zip Embeddable 版 Python ツールのコード インストールしたライブラリ 追加 追加 起動用 bat ファイル
  19. 19. 19© 2019 Toshiba Corporation 03 Excel ファイルの読み込み
  20. 20. 20© 2019 Toshiba Corporation Excel ファイルを読み込む2つのアプローチ [1] https://openpyxl.readthedocs.io/en/stable/ [2] https://www.xlwings.org/ 1. xlsx ファイルを直接開いて読み込む 利点: 実行環境にExcelが不要で、CI にも組み込みやすい ライブラリ: openpyxl [1] など 2. Excel を外部から操作して読み込む 利点: 本物のExcelと同様にファイルを開ける(マクロ実行・再計算可) ライブラリ: xlwings [2] など 採用
  21. 21. 21© 2019 Toshiba Corporation 設定データはテーブルとして表現 openpyxl による Excel テーブルの読み込み テーブル セルの範囲に名前を付け、見出し、 集計行を付ける機能。データ件数 やレイアウトの変更に強くなる。 Excel 2007~。 ただし、openpyxl のテーブルAPIは発展途上 from openpyxl import load_workbook workbook = load_workbook("config.xlsm") # 特定のシートへのアクセス sheet = workbook["機器リスト"] # 読み込み結果を入れる dict devices = {} for table in sheet._tables: if table.name == "Devices": for row in sheet[table.ref]: # 1行分の処理 device = { "name": row[1].value, … } devices[row[0].value] = device
  22. 22. 22© 2019 Toshiba Corporation input["index"] = row[0].value input["name"] = row[1].value input["mode"] = row[2].value データを読み込むコードを毎回書くのは避けたい 読み込みコードの共通化 1/5 0x10 16 or "0x10" ? None, "", or エラー?16 16 or "16" ? device["id"] = row[0].value device["name"] = row[1].value device["sys"] = row[2].value input["index"] = row[0].value input["name"] = row[1].value input["mode"] = row[2].value データの格納 データの変換・バリデーション テーブルの数: 10, 20, 30, …
  23. 23. 23© 2019 Toshiba Corporation テーブルからオブジェクトを作る汎用的な仕組みを導入 読み込みコードの共通化 2/5 a b c d x y z w テーブルA テーブルB class A - a - b - c - d class B - x - y - z - w value が class A の dict value が class B の dict 汎用的な仕組みで 読み込み 列からメンバー変数を作る
  24. 24. 24© 2019 Toshiba Corporation テーブルのスキーマを Excel ファイル内に書けるように 読み込みコードの共通化 3/5 Python コードから アクセスする名前 列番号 dict のキー として使用 型 「?」: 空白→None 読み 込み 機器ID 機器名称 系統 IPアドレス ヘルスチェック OS 種別 10001 メインサーバー1系 1 172.16.0.11 1 Linux 10002 メインサーバー2系 2 172.16.0.12 1 Linux dict テーブル: Devices index: テーブル側の名称変更・順序入れ替え対策 =COLUMN(Devices[機器名称]) – COLUMN(Devices) + 1 Excel ファイル
  25. 25. 25© 2019 Toshiba Corporation スキーマから dataclasses でクラスを自動的に作成 読み込みコードの共通化 4/5 1行を dict にした場合と異なり、 入力補完や型チェックが効くので良い from dataclasses import dataclass @dataclass class Device: id: int name: str sys: int ip_addr: str health_check: str os_type: str dataclasses (主に)データを持つためのクラスを簡単に 定義できるデコレータ。型アノテーションを 付けられる。Python 3.7 ~。 メンバー変数 定義 から を作りたい ※動的に作成した場合には、(今のところ) このメリットがありません。
  26. 26. 26© 2019 Toshiba Corporation 多数の Excel テーブルを扱う体制が整った! make_dataclass 関数で動的にクラスを生成 読み込みコードの共通化 5/5 from dataclasses import make_dataclass members = スキーマからメンバー名と型のdictを作成() ➡ { "id": int, "name": str, "sys": int, "ip_addr": str, … } device_class = make_dataclass("Devices", members) # オブジェクト作成はいつも通り device = device_class(10001, "メインサーバー1系", …)
  27. 27. 27© 2019 Toshiba Corporation 04 設定ファイルの生成
  28. 28. 28© 2019 Toshiba Corporation • 設定ファイルの一部のみを自動生成したい • 段階的に設定ファイル作成を自動化する • フォーマットを変えられないため、きれいではない • アプリケーションを変えられない • 20~30年前から引き継がれたコード • ini 形式で強引にリストを表現 社会インフラシステムの設定ファイル事情 [foo] abc=xyz [bar] A1=1 A2=0 A3=0 A4=1
  29. 29. 29© 2019 Toshiba Corporation テンプレートエンジンで自動生成部分の穴埋めを行い、 それ以外は従来通りテキストエディタで編集 テンプレートエンジンによる設定ファイルの生成 [general] DATE=2019-09-16 MANUAL_SETTING=1 [devices] {{ 自動生成部分 }} テンプレート エンジン テンプレート そのまま出力したい部分と 穴埋め箇所 + 穴埋めルール [general] DATE=2019-09-16 MANUAL_SETTING=1 [devices] DEVICE_ID0=10001 DEVICE_NAME0=メインサーバー1系 DEVICE_ID1=10002 DEVICE_NAME1=メインサーバー2系 DEVICE_ID1=10003 DEVICE_NAME1=操作端末1 : 設定データ 今までの同じ設定ファイル
  30. 30. 30© 2019 Toshiba Corporation {% … %} や {{ … }} の部分を Jinja2 が置き換え テンプレートエンジン: Jinja2 [general] DATE=2019-09-16 MANUAL_SETTING=1 [devices] DEVICE_ID0=10001 DEVICE_NAME0=メインサーバー1系 DEVICE_ID1=10002 DEVICE_NAME1=メインサーバー2系 DEVICE_ID1=10003 DEVICE_NAME1=操作端末1 : 設定ファイル [general] DATE=2019-09-16 MANUAL_SETTING=1 [devices] {% for k, v in devices -%} DEVICE_ID{{ loop.index0 }}={{ k }} DEVICE_NAME{{ loop.index0 }}= {{ v.name }} {% endfor -%} Jinja2 テンプレート 自動生成部分 Ansible と共通化のため、Jinja2 を選択
  31. 31. 31© 2019 Toshiba Corporation 複雑な処理は Jinja2 ではなく Python で書く Jinja2 を使用する上での注意点 よく見かける Jinja2 Q&A Q: ○○をテンプレートに書くには? A: コントローラに書いてください def view_data(): result = [] for k, v in inputs: if v.src_id in devices: name = devices[v.src_id].name elif v.src_id in applications: name = applications[v.src_id].name else: raise Exception(f"エラー: {v.src_id}") result.append((k, v.src_id, name)) return result {% for k, src_id, name in view_data() %} INPUT{{ loop.index0 }}={{ k }},{{ src_id }},{{ name }} {% endfor %} テンプレート テンプレートと一緒にツールに渡す Python コード 例外処理も Python で
  32. 32. 32© 2019 Toshiba Corporation 05 おわりに
  33. 33. 33© 2019 Toshiba Corporation • 継続的インテグレーションでの設定ファイル自動生成 • 設定ファイルを自動生成する仕組みをGitLab CI で構築 • リポジトリに Excel ファイルとテンプレートがコミットされると • コンテナでのツール起動に工夫は不要 • Python製ツールは製品開発部門で 本当にメンテナンスしやすい? • 引継ぎ・メンテナンス機会が少ないのが課題 • 今後評価が必要 その他
  34. 34. 34© 2019 Toshiba Corporation Python で Excel のデータから設定ファイルを生成ツール を次のようなテクニックで開発した まとめ Python で Excel を扱う人口が増えて、 ライブラリなどがより充実することを期待! Python 製ツールの配布 ライブラリを追加した Embeddable 版 Python をツールにバンドル Excel ファイルの読み込み openpyxl による Excel ファイル読み込みと、 スキーマをもとにしたクラス生成・そのオブジェクトへの変換 設定ファイルの生成 テンプレートエンジン Jinja2 の活用

×