こんにちは。アプリケーションチームの栗田です。
業務改善のため Python でツールを作成することがありますが、誰でもかんたんに、できる限り環境依存なく使ってもらえる方法を模索しています。もちろんサーバー構築も解決策のひとつですが、インフラ費用や管理工数を抑えたいですよね。
自前のサーバーなしで Python を実行する方法はいろいろあると思います。
- Python をインストールしてローカル実行する
- Jupyter Notebook(Google Colaboratory)を利用する
- AWS Lambda / Azure Functions を利用する
ただ、開発経験がない人たちにも使ってもらうことを考えると、もう一捻りしたいところです。
そこで、ブラウザ上で Python が実行できる「PyScript」について調べてみたので、備忘録として残します。
PyScriptとは
2022 年に Anaconda 社から発表された、HTML 内に Python で実装したコードを処理してくれるフレームワークです。
Python はインタプリタ言語なので実行環境が必要でしたが、実行環境そのものをブラウザ上で高速動作する WebAssembly 化することで、ブラウザだけで動作可能にするというものです。WebAssembly 化した実行環境である Pyodide がベースになっています。
そのため、Python 標準でないライブラリ(パッケージ)の利用は、Pyodide の仕様に依存するようです。*1
PyScript は執筆時点でアルファ版となります。
本番ワークロードでの利用は非推奨となりますのでご注意ください。
使い方
めちゃくちゃシンプルで、HTML の head タグ内に以下の情報を記載するだけで利用できます。
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
公式サイト には「Install」ボタンがありますが、「Just Kidding, you don't need to install anything.(冗談だよ、インストールいらないよ)」と出てきます。おもしろいですね。
公式サイトに デモ(Hello world) がいくつか準備されています。
実際に試していただけるとわかりますが、表示されるまで少し時間がかかります。(公式も課題として認識されています)
デモ画面の「View Code」ボタンをクリックすると、<py-script>
内に Python コードが書けることがわかりますね。
作ってみた
早速、開発あるあるな改善ツールを作ってみました。【コチラ】 から確認できます。
以下のサンプルコードを index.html として保存し、ブラウザ起動(Chrome がオススメ!)でも OK です。見た目を整えるため、Bootstrap を利用しています。
<html>
<head>
<meta charset="utf-8">
<title>PyScript Sample</title>
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</head>
<body>
<div class="card app-content">
<div class="card-header">
パス変換(Windows <--> Mac)
</div>
<div class="card-body">
<p class="card-text">入力したファイルサーバーのパスを Windows 用(\\xxx\yyy)、Mac 用(smb://xxx/yyy)に変換できます。</p>
<div class="input-group mb-3">
<input id="filepath" type="text" class="form-control" aria-label="Text input with dropdown button">
<button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown"
aria-expanded="false">パス変換</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a py-click="convert_filepath('mac')" class="dropdown-item" href="javascript:void(0)">Windows -> Mac へ</a></li>
<li><a py-click="convert_filepath('win')" class="dropdown-item" href="javascript:void(0)">Mac -> Windows へ</a></li>
</ul>
</div>
</div>
</div>
<div class="card app-content u-margin-top">
<div class="card-header">
Base64 エンコード / デコード
</div>
<div class="card-body">
<p class="card-text">入力した値を Base64 エンコード / デコードできます。</p>
<div class="input-group mb-3">
<textarea id="base64data" class="form-control" rows="5"></textarea>
<button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown"
aria-expanded="false">データ変換</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a py-click="convert_base64('encode')" class="dropdown-item" href="javascript:void(0)">Base64 エンコード</a></li>
<li><a py-click="convert_base64('decode')" class="dropdown-item" href="javascript:void(0)">Base64 デコード</a></li>
</ul>
</div>
</div>
</div>
<div class="card app-content u-margin-top">
<div class="card-header">
JSON 整形
</div>
<div class="card-body">
<p class="card-text">入力した JSON 値を整形して表示できます。</p>
<div class="input-group mb-3">
<textarea id="jsondata" class="form-control" rows="5"></textarea>
</div>
<button py-click="pretty_print_json()" class="py-button btn btn-primary">データ整形</button>
</div>
</div>
<py-script>
import re
import base64
import json
from pyscript import Element
def convert_filepath(param):
try:
input_data = Element("filepath").element.value
if not input_data:
return
if param == "mac":
path = input_data.replace("\\", "/")
path = path.replace("smb:", "")
path = "smb:" + path
Element("filepath").element.value = path
elif param == "win":
path = input_data.replace("smb://", "")
path = path.replace("/", "\\")
path = path.replace("\\\\", "")
path = "\\\\" + path
Element("filepath").element.value = path
except:
print("Invalid input data: ", input_data)
def convert_base64(param):
try:
input_data = Element("base64data").element.value
if not input_data:
return
if param == "encode":
encoded_str = base64.b64encode(input_data.encode('utf-8')).decode()
Element("base64data").element.value = encoded_str
elif param == "decode":
decoded_str = base64.b64decode(input_data).decode('utf-8')
Element("base64data").element.value = decoded_str
except:
print("Invalid input data: ", input_data)
def pretty_print_json():
try:
input_data = Element("jsondata").element.value
if not input_data:
return
parsed = json.loads(input_data)
Element("jsondata").element.value = json.dumps(parsed, indent=4, sort_keys=True)
except ValueError as e:
print("Invalid JSON: ", e)
</py-script>
</body>
<style type="text/css">
body {
padding: 24px 16px;
}
.app-content {
width: 800px;
margin: 0 auto;
}
.u-margin-top {
margin-top: 24px;
}
</style>
</html>
「いやいや、これぐらいコマンドで一発変換できるでしょ」と言われればその通りです!
ここではイメージを掴んでいただければ十分です。日常的に繰り返しやっている細かな作業をこういったツールで効率化できそうではないでしょうか。
<a py-click="convert_filepath('mac')" ...
や <button py-click="pretty_print_json()" ...
のように、py-click
で Python の関数を指定すれば実行できます。かんたんですね。
他にも matplotlib
や numpy
などデータ可視化・分析用のライブラリも使用できます。詳しくは公式サイトに デモ(Matplotlib) があるのでご確認ください。
静的なページなので、AWS S3 などに公開するだけで Web アプリとして利用できるのがいいですね。*2
おわりに
実は今回実装したサンプルコード、そのほとんどを ChatGPT に生成いただきました。
エムオーテックスでは、ChatGPT を活用した独自の AI システム「Smart ばんにゃ」が導入されており、社員全員が気軽に AI チャットを利用することができます。詳細はこちらの記事をご覧ください。note.com
ChatGPT 上で Python を実行できる「Code Interpreter」もありますし、組み合わせることで何か大きな価値の創出につなげることができるかもしれません。
テキストエディタとブラウザさえあれば試せるので、ぜひ手を動かしてみてください!
以上、PyScript に関する記事でした。
ご興味あれば採用サイトのほうもぜひご確認ください
www.motex.co.jp
ここまでお読みいただきありがとうございました。