概要
pythonのウェブフレームワークflaskでサーバーを立てて、立てたエンドポイントに向かって何かオブジェクト(例えば文字列とか、リストとか、自作クラスのオブジェクトとか)を送りたいときの話。
毎回忘れてしまうことも多いと思うので、ここにまとめておきます。
忙しい人への結論
送る側は、
- 送りたいものを文字列にして、
- ディクショナリに入れて、
json.dumps()
して送るのが一番(自分は)楽だと思います。
受け取る側は、データを受け取って、送る側がした作業を逆からやります。
-
request.data
でデータの受け取り -
json.loads()
で文字列からディクショナリに戻す。 - ディクショナリから値を取り出す。
- 値を元の型に戻す。
やりかた
流れはこうなります。概要です。
最終的にオブジェクトを文字列にして、その文字列をdictに入れて、json.dumpsしてから送る方法をよく使っています。
送る側.py
〜〜〜〜
送りたいもの = something
case1 isinstance(送りたいもの, 何らかのクラスオブジェクト): ## もし送りたいものがオブジェクトのとき
if 送りたいもの can be binalized: ## もしオブジェクトがバイナリにできるとき
'pickle.dumps()でオブジェクトをバイナリ(byte)にしましょう。'
my_binary = pickle.dumps(送りたいもの)
GO_TO case2
else: ## もしオブジェクトがバイナリにできないとき
'なんらかの方法でバイナリにするか、自作のclassオブジェクトの場合、
シリアライズ関数を書く必要があります。たとえば、クラスがもつメンバ変数を全てディクショナリに書き出すような関数です。たとえば、to_dict()関数を実装する。'
my_binary = 送りたいもの.to_dict()
GO_TO case4
case2 isinstance(送りたいもの, byte): ## もし送りたいものがbyteのとき
'送りたいものをbase64.b64encode()で文字列化しましょう。'
my_str = base64.b64encode(送りたいもの)
GO_TO case3
case3 isinstance(送りたいもの, str): ## もし送りたいものがstr(文字列)のとき
'ディクショナリに入れましょう。'
my_dict = {"my_object": 送りたいもの}
GO_TO case4
case4 isinstance(送りたいもの, dict): ## もし送りたいものがすでにdictのとき
'送りたいものを json.dumps()したら、準備完了です。'
送りたいもの = json.dumps(送りたいもの)
EXIT_CASE
assert type(送りたいもの) = 文字列(str), '最初に戻ってください。'
## print(送りたいもの)
## >>> '{"my_object": my_value}'
requests.post(url="<送り先のエンドポイント>", 送りたいもの,
headers={'Content-Type': 'application/json'})
受け取る側.py
〜〜〜〜
@app.route('/receive')
def receive():
data = request.data ## post で送られてきた「送りたいもの」はrequest.dataで受け取れます。
data = json.loads(data)['my_object'] ## まずはjson.loadsでディクショナリにもどして、
## keyがmy_objectの値(文字列になっている送られてきたもの)を受け取ります。
if dataをバイナリ(byte)に戻したいとき:
'data をbase64.b64decode()でbyteにデコードしましょう。'
data2 = base64.b64decode(data)
elif dataをクラスオブジェクトに戻したいとき:
if もしpickle.loadsで戻せるとき:
data3 = pickle.loads(data2)
else もし自作クラスのオブジェクトなどで、pickleが使えないとき:
'自身でdeserialization関数、dict_to_obj()のような関数を実装して、元のクラスオブジェクトに戻しましょう'
data3 = dict_to_obj(data2)
まとめ
今回は、flaskで立てたエンドポイントに向かってなにかオブジェクトをpostするときのやり方をまとめました。
今回はこの辺で。
おわり。