概要
Python Requestsを使って、multipart/form-data
を送る場合、open
で開いたファイルを送る仕様となっている。
Pythonの辞書形式のデータをJSONファイルとして送る場合、一時的にJSONファイルを作成せずに送る方法が分からなかった。
Python Requestsを使ってmultipart/form-dataをin-memoryで送る方法を記す。
Python Requestsの仕様
Python Requestsを使って、multipart/form-data
を送る場合、open
で開いたファイルを送る仕様となっている。
https://requests-docs-ja.readthedocs.io/en/latest/user/quickstart/#id7
import requests
url = "https://example.com"
headers = {
"Content-Type": "multipart/form-data",
}
files = {
'file': ('report.xls', open('report.xls', 'rb'))
}
response = requests.post(url, headers=headers, files=files)
解決方法
JSON(辞書データ)を送りたい場合
from io import BytesIO
import json
import requests
url = "https://example.com"
data = {"hoge":"hoge"}
headers = {
"Content-Type": "multipart/form-data",
}
binary_stream = BytesIO(json.dumps(data).encode('utf-8'))
files = {
"file": ("filename.json", binary_stream),
}
response = requests.post(url, headers=headers, files=files)
解説
open
で何を呼び出しているかというと、バイナリストリームのオブジェクトである。
io
のリファレンスを読むと以下のように書いてある。
https://docs.python.org/ja/3/library/io.html#module-io
バイナリー I/O (buffered I/O とも呼ばれます) は bytes-like オブジェクト を受け取り bytes オブジェクトを生成します。エンコード、デコード、改行文字変換は一切行いません。このカテゴリのストリームは全ての非テキストデータや、テキストデータの扱いを手動で管理したい場合に利用することができます。
バイナリーストリームを生成する一番簡単な方法は、 open() の mode 文字列に 'b' を指定することです:
f = open("myfile.jpg", "rb")
BytesIO はインメモリーのバイナリストリームです:
f = io.BytesIO(b"some initial binary data: \x00\x01")
バイナリーストリーム API は BufferedIOBase のドキュメントで詳しく解説します。
ということで、open()
でファイルからバイナリストリームオブジェクトを生成する代わりに、io.BytesIO()
でインメモリのバイナリストリームを生成する。
辞書データからバイナリストリームまでの道のり
from io import BytesIO
import json
# 元なる辞書
data = {"hoge":"hoge"}
# JSONとして、Stringに変換
string_data = json.dumps(data)
# utf-8形式でバイトに変換、
bytes_data = string_data.encode('utf-8')
# バイトデータをバイナリストリームに変換
binary_stream = BytesIO(bytes_data)
もちろん、JSON以外にCSVやXMLなどもインメモリで作成し、そのまま requests
でmultipart/form-data
として送ることが可能。
参考記事
辞書データをJSONに変換し、BytesIOオブジェクトにする方法の参考にした。
https://stackoverflow.com/questions/53118672/what-is-correct-way-to-load-json-file-stored-in-the-bytesio-object
open
と BytesIO
オブジェクトの違いについて参考にした。
https://stackoverflow.com/questions/42800250/difference-between-open-and-io-bytesio-in-binary-streams