Python: Jak użyć requests do wysłania danych JSON, danych POST, argumentów w url i plików do serwera aiohttp.web
Dane JSON
requests używa json= do wysyłania JSON i automatycznie zamienia na text i dodaje nagłówek 'Content-Type': 'application/json'.
import requests
r = requests.post('http://0.0.0.0:8080/test', json={'param1': 'value1', 'param2': 'value2'})
To samo z użyciem standardowego data= .
import requests
import json
r = requests.post('http://0.0.0.0:8080/test',
data=json.dumps({'param1': 'value1', 'param2': 'value2'}),
headers={'Content-Type': 'application/json'},
)
aiohttp.web odbiera to za pomocą await request.json().
Może wyrzucić błąd gdy nie ma danych JSON.
Czyta dane ze strumienia więc może wyrzucić błąd jeśli inna funkcja już pobrała dane ze strumiemia.
from aiohttp import web
routes = web.RouteTableDef()
@routes.post('/test')
async def test(request):
try:
print('JSON:', await request.json()) # json data as dictionary/list
except Exception as ex:
print('JSON: ERROR:', ex)
return web.Response(text='Received...')
app = web.Application()
app.add_routes(routes)
if __name__ == '__main__':
web.run_app(app)
Dane POST
requests używa data= do wysłania jako standardowe dane POST.
import requests
r = requests.post('http://0.0.0.0:8080/test', data={'param1': 'value1', 'param2': 'value2'})
aiohttp.web odbiera to za pomocą await request.post().
Nie wyrzuca błędu gdy nie ma danych POST.
Czyta dane ze strumienia więc zwraca puste dane jeśli inna funkcja już pobrała dane ze strumiemia.
from aiohttp import web
routes = web.RouteTableDef()
@routes.post('/test')
async def test(request):
print('POST :', await request.post()) # POST data
return web.Response(text='Received...')
app = web.Application()
app.add_routes(routes)
if __name__ == '__main__':
web.run_app(app)
Argumenty w URL
requests używa params= do wysłanie wartości w adresie url.
Automatycznie używa uses urllib.parse do zamiany w tekst ?param1=value1¶m2=value2.
Jeśli w danych są specialne znaki to użyje wartości %code.
import requests
r = requests.post('http://0.0.0.0:8080/test', params={'param1': 'value1', 'param2': 'value2'})
aiohttp.web odbiera to za pomocą request.query_string (jaki tekst ?param1=value1¶m2=value2)
lub request.query (jaki słownik {'param1': 'value1', 'param2': 'value2'}).
Nie wyrzuca błędu gdy nie ma danych w adresie url.
Nie czyta danych ze strumienia więc nie ma to konfliktu z innymi funkcjami.
from aiohttp import web
routes = web.RouteTableDef()
@routes.post('/test')
async def test(request):
print('ARGS string:', request.query_string) # arguments in URL as string
print('ARGS :', request.query) # arguments in URL as dictionary
return web.Response(text='Received...')
app = web.Application()
app.add_routes(routes)
if __name__ == '__main__':
web.run_app(app)
PLIKI
requests używa files= do wysłania plików. Używa do tego listy z tuplami/krotkami.
Każda tupla opisuje jeden plik. Zawiera ona nazwę pola (jak w formularzu w HTML), uchwyt do pliku (open(...)) lub dane z pliku (open(...).read())
import requests
r = requests.post('http://0.0.0.0:8080/test', files=[('file', open('client.py'))])
aiohttp.web odbiera to za pomocą await request.multipart().
Wyrzuca błąd gdy nie ma plików.
Czyta dane ze strumienia więc może wyrzucić błąd jeśli inna funkcja już pobrała dane ze strumiemia.
from aiohttp import web
routes = web.RouteTableDef()
@routes.post('/test')
async def test(request):
try:
#print('MULTIPART:', await request.multipart()) # files and forms
reader = await request.multipart()
print('MULTIPART:', reader)
while True:
part = await reader.next()
if part is None:
break
print('filename:', part.filename)
print('>>> start <<<')
print(await part.text())
print('>>> end <<<')
except Exception as ex:
print('MULTIPART: ERROR:', ex)
return web.Response(text='Received...')
app = web.Application()
app.add_routes(routes)
if __name__ == '__main__':
web.run_app(app)
BODY
aiohttp.web ma także funkcje to pobierania surowych danych z body.
Funkcje te nie wyrzucają błędu ale zwracają puste dane jeśli inna funkcja już pobrała dane ze strumiemia.
print('BODY bytes :', await request.content.read()) # body as bytes
print('BODY string:', await request.text()) # body as string
Notatki:
| URL | POST | JSON | FILE | BODY | |
|---|---|---|---|---|---|
| async/stream/body | NO | YES | YES | YES | YES |
| raise error | NO | NO | YES | YES | NO |
Funkcje, które czytają ze strumienia (POST, JSON, FILE, BODY) mogą nie zwrócić danych jeśli inna z tych funkcji wcześniej czytała dane.
Original pytanie na Stackoverflow: aiohttp.web post method get params
furas.pl