Search on blog:

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&param2=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&param2=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

If you like it
Buy a Coffee