Python の attrs で validation をかける
以前 Qrunch に投稿してた記事を持ってきました。
Python の attrs が便利すぎて、データ保持用のクラスを作る時なんかは専らコレばっかり使っています。
そんな attrs で入力されるデータに validation をかける方法です。
attrs で入力データをチェック
例えば Pose
というクラスに対して、位置を表す position
は長さ 3 の配列、向きを表す orientation
は長さ 4 の配列(クォータニオン) であることをチェックする場合は以下のように書くことができます。
from attr import attrs, attrib @attrs class Pose: position = attrib() orientation = attrib() @position.validator def check_position(self, attribute, value): if len(value) != 3: raise ValueError("position must be a list with size=3") @orientation.validator def check_orientation(self, attribute, value): if len(value) != 4: raise ValueError("orientation must be a list with size=4")
正しい値を代入した場合
>>> Pose(position=[0, 1, 2], orientation=[0, 0, 0, 1]) Pose(position=[0, 1, 2], orientation=[0, 0, 0, 1])
不正な値を代入した場合
>>> Pose(position=[0, 1], orientation=[0, 0, 0, 0, 1]) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<attrs generated init d25cdc317f9cca07dcc37d3210f62862e6055553>", line 5, in __init__ File "<stdin>", line 8, in check_position ValueError: position must be a list with size=3
普通の class だと __init__
が肥大化したりしがちですが、これだとスッキリ書けますね!
関連サイト
周波数からC3やF4などのノート名に変換する
以前 Qrunch に投稿してた記事を持ってきました。
Python 3 で周波数からノート名に変換
A4 は 440Hz、 C3 は 130.8Hz のようにノート毎に周波数が決まっていますが、周波数からノートに変換するコードを Python 3 で書いてみました。
import math SCALE_LIST = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] C0_FREQUENCY = 16.35 def frequency_to_note(freq): n = round(math.log2(freq / C0_FREQUENCY) * 12) return SCALE_LIST[n % 12] + str(n // 12)
実行するとこんな感じ。ノートの音程ぴったりじゃない場合は四捨五入で丸めています。
>>> frequency_to_note(55) 'A1' >>> frequency_to_note(440) 'A4' >>> frequency_to_note(130) 'C3' >>> frequency_to_note(185) 'F#3'
参考URL
TRIX - ゴクロウサンの歌詞
ずっと聞き取れないところがあるなーと思っていたんだけど、イヤホンを変えてみたらだいぶ聞き取りやすくなったのでメモメモ。
毎朝満員電車に揺られてゴクロウサン あぁ大変だ
会社で家庭で小言を言われてゴクロウサン もうたくさんです
毎朝満員電車に揺られてゴクロウサン あぁ大変だ
会社で家庭で小言を言われてゴクロウサン もうたくさんです
朝から早起き育児にパートにゴクロウサン あぁ大変だ
毎日炊事に掃除に洗濯ゴクロウサン もうたくさんです
朝から晩まで営業スマイルゴクロウサン あぁ大変だ
景気が全く回復しないや困ったなぁ もうたくさんです
毎朝満員電車に揺られてゴクロウサン あぁ大変だ
会社で家庭で小言を言われてゴクロウサン もうたくさんです
フュージョンバンドだし歌詞サイトには載ってないしで、ずっとモヤモヤしてたんだけどコレでスッキリ!
Pythonでファイルに書き出さずにzip圧縮
この記事では、Python でファイルを生成せずに zip 圧縮したデータを生成する方法を紹介します。
zip 圧縮したデータを Python 内からアップロードしたい場合なんかに、ファイルに書き出して後から削除する手間を避けたかったり、FaaS などそもそも ReadOnly のファイルシステムで使ったりすることを想定しています。
動作環境
- Python 3.7
動かし方
Python の zipfile ライブラリと、 io.BytesIO を用いて実現します。
# zip 圧縮したデータをファイルに書き出す代わりに BytesIO のストリームを作成 zip_stream = io.BytesIO() # ファイルに書き出す代わりに zip_stream に zip 圧縮したデータを出力 with zipfile.ZipFile(zip_stream, 'w', compression=zipfile.ZIP_DEFLATED) as new_zip: # foo.txt というファイル名で abcdef という文字列をzipファイルに追加 new_zip.writestr("foo.txt", "abcdef") # ローカルの foo.png を zip ファイルに追加 new_zip.write("foo.png") # 生成された zip 圧縮データを出力 # 実際には print の代わりに HTTP の POST とか、S3 へのアップロードとかに使うイメージ print(zip_stream.getvalue())
参考URL
AWS Lambda で Python3 + Chainer を使う方法
概要
Python3 + Chainer を使った API を AWS の API Gateway + Lambda で動かす方法を紹介します。
ちなみに Deep Chord というウェブアプリのバックエンドで使っています。
以下の2点がポイントです。
動作環境
方法
EC2 上で Chainer をビルド
Amazon Linux 2 の EC2 インスタンスを立ち上げ、以下のコマンドで Chainer をインストールします。インスタンスは t2.micro などの無料のインスタンスで十分です。
# Lambda で動かす Python のバージョンと合わせます sudo yum -y install python37 python37-pip # Chainer のインストール (Numpyなども一緒にインストールされます) pip3.7 install chainer==1.12 --user
生成されたファイルのダウンロード
Chalice のプロジェクトの vendor フォルダに上記でビルドされた Chainer とその依存ライブラリをダウンロードします。
# Chalice のプロジェクトを作成(作成済みの場合は省略) chalice new-project プロジェクト名 # プロジェクト内に vendor フォルダを作成 cd プロジェクト名 mkdir vendor # vendor フォルダ内に EC2 でビルドしたライブラリをダウンロード scp -r -i [秘密鍵のパス] ec2-user@[EC2のIPアドレス]:./.local/lib/python3.7/site-packages/ ./vendor/
app.py の作成
Chalice プロジェクトの requirements.txt
には chainer は書かず、あとは普通に app.py
の中で import chainer
すると、vendor
フォルダ内の chainer を参照してくれます。
参考情報
numpy とかは requirements.txt
に書いておくだけで、例えば Mac 上で開発してても Lambda (というかAmazon Linux) で動くようにいい感じに Chalice がビルドしてデプロイしてくれるらしい。Chainer も最新版なら大丈夫なのかな?
ダウンロードした vendor フォルダを覗いてみたら .so
ファイルは Chainer じゃなくて、 Chainer が依存している protobuf とかの中に入ってた。ローカルでのビルドは依存ライブラリ側の方で失敗しているのかも...
参考URL
免責事項
※ 投稿内容は個人的な見解であり、所属する企業を代表するものではありません。