python:requestsを使ってリクエストボディのついたGETリクエストを送出する
トナミです。表題通りの事します。
GETリクエストにリクエストボディつけて送ってくれと言われてンェー何それという気持ちが発生しました。
調べてみるとGETリクエストにおけるリクエストボディの取扱はRFCに記述がありません(=未定義です)。
なんでまー、クライアントにしろサーバにしろ、好きに実装してねという状態のようです。
ソースコードの組み合わせで君だけの最強のGETリクエストにおけるリクエストボディの取扱を実装しろ!
というわけでやります。とは言え一般的でないため、簡単に調べても出てきません。
この手の話題「pythonでHTTP通信!」みたいなエントリーがヒットしまくりググラビリティが低すぎで涙出ます。
とりあえず普段使ってるrequestsさんで出来ないか考えましょう。requestsの基本的な使い方は省略します。
postの時はリクエストボディを付与出来て、getの時は普通にやると付与されないという認識があります。
まず両者の違いですが
def get(url, params=None, **kwargs): r"""docstring長いので省略 """ kwargs.setdefault('allow_redirects', True) return request('get', url, params=params, **kwargs)
これがget
def post(url, data=None, json=None, **kwargs): r"""docstring長いので省略 """ return request('post', url, data=data, json=json, **kwargs)
これがpost
という感じです。
キーワード引数が違うだけで、最終的に全部突っ込んでrequest()している事が分かります。
ここでrequestが何かと言うと
def request(method, url, **kwargs): """ (docstringには他にも色々と大事な事が書いてあるんですが、長かったので抜粋) :param params: (optional) Dictionary, list of tuples or bytes to send in the query string for the :class:`Request`. :param data: (optional) Dictionary, list of tuples, bytes, or file-like object to send in the body of the :class:`Request`. """ # By using the 'with' statement we are sure the session is closed, thus we # avoid leaving sockets open which can trigger a ResourceWarning in some # cases, and look like a memory leak in others. with sessions.Session() as session: return session.request(method=method, url=url, **kwargs)
という感じになってます。
結局mthodの種類とrequest投げる先の情報以外は全部突っ込まれているということです。
んでdocstringを見ると、paramsはquery stringへ、dataはbodyへ行くぜ!という事が書いてあります。わかりやすい
(余談:docstringにコピペミスがあってoss貢献チャンスかと思いきや、自分のrequsetsがちょっと古かっただけで修正済みでした。)
つまり考えはこうです。
postの時にリクエストボディが設定されてるのは、dataに要素を渡しているから。
getの時にリクエストボディが生まれないのは、paramsにしか要素を渡していないから。
kwargsのところに入れてしまえば、どんなパラメータも最後は同じ出口から送出されていく。
んじゃgetリクエスト打つ時にdataを定義すればリクエストボディにしてもらえるんじゃねえの?
実際にやってみます
from flask import Flask, request import json app = Flask(__name__) @app.route('/test', methods=['GET']) def test(): body = json.loads(request.data) print(body) return body['test'] if __name__ == "__main__": app.run(host='0.0.0.0', port=8080, debug=True)
こんな感じに適当に立てたflaskサーバにリクエストを投げ、'bodydata'が取り出せるか確認します。
※flaskにおいてリクエストボディの内容はrequset.dataで取り出せるということになっています。
私は甘いのでここの検証をしていません
投げるソースはこんな
import requests import json url = 'http://localhost:8080/test' data = {'test': 'bodydata'} response = requests.get(url, data=json.dumps(data)) print(response.text)
サーバ側のソースを実行するとlocalhost:8080にFlaskくんが立つので、投げるソースを実行して似非通信をしてます。
localhostに立ってるサーバに同一ホストからリクエスト投げた、というのが検証として妥当なのか検証していません。
上記ソースをアレするとサーバ側でもクライアント側でもいい感じの値が取れてる事を確認出来ます。
これでGETリクエストにリクエストボディをつける事が出来、この問題を解く事が出来ました。よかったですね
マサカリお待ちしております。
おわり
二酸化炭素センサーとRaspberry Piを破壊する
ハロートナミ
mh-z19というセンサーを購入し部屋の二酸化炭素濃度測ろうとして破滅したという話をします。
まず最初にやりたかった事です
はい
上記エントリを読むと
- Raspberry Piを買う
- mh-z19を買う
- いい感じにつなぐ
- pip install mh-z19
- sudo python -m mh_z19
で部屋の二酸化炭素が測れる事が分かります。
それではやっていきましょう
Raspberry Piは家にあった(T先生に誕生日に頂きました。多謝)
まずmh-z19を買います
www.banggood.comこういう感じで海外通販サイトから買います。Amazonにもあるけど高い
上記やつを買って忘れた頃に届きました。
届いた後とりあえずチャレンジしていきます。一回目はゴールデンウィークにやりました。
爆発的な発熱があり、何も起きないことが分かりました。この時点で不穏です
とにかく動かないのでセンサーが不良品だったor一瞬にしてセンサーをぶち壊した事を考えて買い直します。2個目はebayで買いました。
忘れた頃にドイツから届きました。なんで
再びmh-z19 接続とかで検索しながら接続してみます。発熱を感じます。
前回と同じ感覚です。もしかしたら正常に接続出来ていて、これはプレヒートと呼ばれるものなのか?わかりませんが少し待ってみましょう
ブレッドボードが溶けました。狂っている。センサーは反応せず、なんならRaspberry Piも起動しなくなりました
もはや完全にやる気をなくしました。繋いでpip install hogeするだけで使えるセンサーを一瞬で2個破壊したセンスがキツい。あと誕生日プレゼントで貰ったRaspberry Piが虚無に消えたのがキツい
ツイッテレで有識者に色々聞いた結果
- テスターを買え
- 回路図を書け
- よく分かってない事をするな
- バカ
- オームの法則を勉強しろ
という感じの意見が集まります。全てその通りだと思います
結局電気とか電流とかの気持ちが分かってないのに回路を作ろうとする事自体が間違っていて、ネットに書いてある通りにやれば出来るなんて甘い世界はどこにもないということです。
悔しい気持ちになったので全部揃え直す事にしました。コネクタとかジャンパー線とかもちゃんと端子にあったものを揃えます。もうAmazonで3個目のmh-z19も買ったしテスターも買いました。Raspberry Pi本体も買ったしOS書き込み用sdカードも買った。練習用に温度センサのDHT11も買った。オライリーの小学生向けRaspberry Pi入門みたいなのも買います。(センサーを壊し続ける作業で既に2万円以上使っており、回路入門の険しさを感じています)
全部揃え直したら電気とか電流の概念に謝罪した後DHT11で温度を測るをやりますが、どうせDHT11もネットで調べて適当に繋ぐとかやると壊れると思うのでデータシート等ドキュメントを全て理解するまで触らないようにします。
ソフトウェアはとりあえず動かしてから考えるが出来ますが、それをハードウェアでやると壊れるということがよく分かりました。
教養が無いと回路を作る事も出来ません。勉強をしましょう
もう少し賢くなりたいですね
おわり