Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
Python で 自力シリアライズ すごい広島 .rb with Python[75] オンライン LTDD 2023-06 #1 @tsuda_ahr
Slide 2
Slide 2 text
お題 Python でシリアライズしたい。(ただしバイナリーで)
Slide 3
Slide 3 text
pickle を使えばいいよ、という情報をもらう
Slide 4
Slide 4 text
だめだった • バイナリーでシリアライズしたいだけでなく、型や配置などを制御したい。
Slide 5
Slide 5 text
どういうこと? • C言語の構造体/共用体や C# の FieldOffset みたいなことがしたい。 • (=メモリマッピングを制御したい) offset 0 0xf0 long lg (0x12345678abcdef0) int i1 (0x9abcdef0) 1 0xde 2 0xbc 3 0x9a 4 0x78 int i2 (0x12345678) 5 0x56 6 0x34 7 0x12 8 0x18 double d (0x400921fb54442d18) (3.141592653589793) 9 0x2d 10 0x44 11 0x54 12 0xfb char c (0x21fb) 13 0x21 14 0x09 byte b (0x09) 15 0x40
Slide 6
Slide 6 text
と、いうことで自作してみる
Slide 7
Slide 7 text
1. まずクラス定義 class Hoge: a:'I' = 0 # int16 b:'C10' = '' # char[10] c:'L' = 0 # int32
Slide 8
Slide 8 text
なにこれ? • アノテーションっていうの? • マニュアル(?)的には「Syntax for Variable Annotations」「型ヒント」 とか言われているっぽい機能の模様。 • クラスを vars で覗くと出てくる。
Slide 9
Slide 9 text
other-uses-of-annotations ? (他の使用方法?) • “アノテーションの好ましい使用方法として、型ヒンティングを明示的に推奨し ますが、型じゃないものをクォーテーションで括って指定してもエラーにはな らないよ”? https://peps.python.org/pep-0526/
Slide 10
Slide 10 text
2. インスタンスを作る hoge = Hoge() hoge.a = 1 hoge.b = '123ABC' hoge.c = 65538
Slide 11
Slide 11 text
3. アノテーションの取得と結果の初期化 annots = Hoge.__annotations__ result = bytes()
Slide 12
Slide 12 text
4. ライブラリの読み込み忘れてた(汗 import re import struct
Slide 13
Slide 13 text
struct? • “このモジュールは、Pythonの値とPythonバイトオブジェクトとして表現さ れるC構造体との間の変換を行います。コンパクトなフォーマットの文字列は、 Pythonの値との間で意図された変換を記述します。このモジュールの関数 とオブジェクトは、外部ソース(ファイルやネットワーク接続)とのデータ交換、 あるいはPythonアプリケーションとC層との間のデータ転送という、大きく 異なる2つの用途に使用することができます。” • C言語の struct とは異なる。その名を関したライブラリであることに注意。
Slide 14
Slide 14 text
4. メンバーのアノテーションと値を読み込み for var_name in annots.keys(): # 値の取得 value = getattr(hoge, var_name) # アノテーションの取得 annot = annots.get(var_name) # アノテーションのパース m = re.match(r'^(?P[A-Z])(?P[0-9]*)$', annot)
Slide 15
Slide 15 text
5. 変換(数値) # short 型(INT16)の値をエンコード if m.group('type') == 'I': result += struct.pack('
Slide 16
Slide 16 text
5. 変換(文字列) # sjis string の値をエンコード if m.group('type') == 'C': # 指定長を数値化して偶数値に切り上げ length = (int(m.group('length')) + 1) // 2 * 2 # エンコード a = value.encode('Shift-Jis') # 末尾の null padding a += bytes(length) result += a[0:length]
Slide 17
Slide 17 text
結果 >>> result b'¥x01¥x00123ABC¥x00¥x00¥x00¥x00¥x02¥x00¥x01¥x00' offset 0 0x01 INT16 a (1) 1 0x00 2 0x31 Char[10] b ('123ABC') 3 0x32 4 0x33 5 0x41 6 0x42 7 0x43 8 0x00 9 0x00 10 0x00 11 0x00 12 0x02 INT32 c (65538) 13 0x00 14 0x01 15 0x00
Slide 18
Slide 18 text
結論 • C# でいうところの属性はアノテーションで代替できる。 • ただし、変数に対してアノテーションは一つしか定義できなさそう。 (C# の属性は複数定義できる) • ユーザー定義のアノテーションを使ってしまうと型ヒントとしてつかえなさそ う。 • なんだけど、これで自作のシリアライザーは作れそう。
Slide 19
Slide 19 text
もし代案があれば? • もし、もっと良い方法とかあればご教示ください(ぇ
Slide 20
Slide 20 text
ご清聴ありがとうございました。