portaldacalheta.pt
  • Põhiline
  • Tulud Ja Kasv
  • Protsess Ja Tööriistad
  • Investorid Ja Rahastamine
  • Puldi Tõus
Tagumine Ots

WSGI: Pythoni serveri-rakenduse liides



1993. aastal oli veeb veel lapsekingades, umbes 14 miljonit kasutajat ja 100 veebisaiti . Lehed olid staatilised, kuid juba oli vaja luua dünaamilist sisu, näiteks ajakohaseid uudiseid ja andmeid. Sellele reageerides rakendasid Rob McCool ja teised kaastöötajad riikliku superarvutirakenduste keskuses (NCSA) Common Gateway Interface'i (CGI). HTTPd veebiserver (Apache'i eelkäija). See oli esimene veebiserver, mis suutis teenida eraldi rakenduse loodud sisu.

Sellest ajast alates on Interneti-kasutajate arv plahvatuslikult kasvanud ja dünaamilised veebisaidid on muutunud üldlevinudiks. Esmakordselt uue keele õppimisel või isegi kodeerimise õppimisel tahavad arendajad piisavalt kiiresti teada, kuidas oma kood veebi siduda.



Python veebis ja WSGI tõus

Pärast CGI loomist on palju muutunud. CGI-lähenemine muutus ebapraktiliseks, kuna see nõudis iga taotluse korral uue protsessi loomist, raisates mälu ja protsessorit. Ilmusid veel mõned madalama taseme lähenemisviisid, nagu FastCGI] (http://www.fastcgi.com/) (1996) ja mod_python (2000), pakkudes erinevaid liideseid Pythoni veebiraamistike ja veebiserveri vahel. Erinevate lähenemisviiside vohamise tõttu piiras arendaja raamistiku valik lõpuks veebiserverite valikuid ja vastupidi.



Selle probleemi lahendamiseks tegi 2003. aastal ettepaneku Phillip J. Eby PEP-0333 , Pythoni veebiserveri lüüsi liides (WSGI). Idee oli pakkuda kõrgetasemelist universaalset liidest Pythoni rakenduste ja veebiserverite vahel.



2003. aastal PEP-3333 värskendas WSGI-liidest Python 3 toe lisamiseks. Tänapäeval kasutavad peaaegu kõik Pythoni raamistikud WSGI-d kui (kui mitte ainsat) vahendit oma veebiserveritega suhtlemiseks. See on nii Django , Kolb ja paljud teised populaarsed raamistikud teevad seda.

Selle artikli eesmärk on anda lugejale pilk WSGI toimimisele ja võimaldada lugejal ehitada lihtne WSGI-rakendus või server. See ei ole siiski ammendav ja arendajad, kes kavatsevad juurutada tootmiseks valmis servereid või rakendusi, peaksid põhjalikumalt uurima WSGI spetsifikatsioon .



Pythoni WSGI-liides

WSGI määratleb lihtsad reeglid, millele server ja rakendus peavad vastama. Alustame selle üldise mustri ülevaatamisest.

milleks node js-i kasutatakse

Pythoni WSGI serverirakenduse liides.



Rakenduse liides

Python 3.5-s on rakenduse liidesed järgmised:

def application(environ, start_response): body = b'Hello world! ' status = '200 OK' headers = [('Content-type', 'text/plain')] start_response(status, headers) return [body]

Python 2.7-s ei oleks see liides palju erinev; ainus muudatus oleks see, et keha esindab tähis str objekti asemel bytes üks.



Kuigi oleme antud juhul funktsiooni kasutanud, on ükskõik milline helistatav teeb. Siinsed rakenduse objekti reeglid on järgmised.

  • Peab olema helistatav kasutajaga environ ja start_response parameetrid.
  • Peab helistama start_response enne keha saatmist tagasihelistamine.
  • Peab tagastama iterable koos dokumendi keha tükkidega.

Teine näide objektist, mis vastab nendele reeglitele ja tooks sama efekti, on järgmine:



class Application: def __init__(self, environ, start_response): self.environ = environ self.start_response = start_response def __iter__(self): body = b'Hello world! ' status = '200 OK' headers = [('Content-type', 'text/plain')] self.start_response(status, headers) yield body

Serveri liides

WSGI-server võib selle rakendusega liidestuda niimoodi:

def write(chunk): '''Write data back to client''' ... def send_status(status): '''Send HTTP status code''' ... def send_headers(headers): '''Send HTTP headers''' ... def start_response(status, headers): '''WSGI start_response callable''' send_status(status) send_headers(headers) return write # Make request to application response = application(environ, start_response) try: for chunk in response: write(chunk) finally: if hasattr(response, 'close'): response.close()

Nagu võisite tähele panna, start_response helistatav tagastas a write helistatav, mida rakendus võib kasutada andmete kliendile tagasi saatmiseks, kuid seda ei kasutatud meie rakenduse koodi näites. See write liides on aegunud ja me võime seda praegu eirata. Sellest räägitakse põgusalt artiklis hiljem.



Serveri kohustuste teine ​​eripära on helistada valikulisele close meetod iteraatoril, kui see on olemas. Nagu Graham Dumpletoni artiklis märgitud siin , on see WSGI sageli tähelepanuta jäetud funktsioon. Selle meetodi kutsumine kui see on olemas , lubab rakendusel vabastada ressursse, mis tal veel võivad olla.

Rakenduse helistatav environ Argument

environ parameeter peaks olema sõnaraamatu objekt. Seda kasutatakse taotluste ja serveriteabe edastamiseks rakendusse, täpselt samamoodi nagu CGI. Tegelikult kehtivad WSGI-s kõik CGI-keskkonnamuutujad ja server peaks edastama kõik rakenduse kohta kehtivad.

Kuigi on palju valikulisi võtmeid, mida saab edasi anda, on mitu neist kohustuslikud. Võttes näiteks järgmise GET taotlus:

$ curl 'http://localhost:8000/auth?user=obiwan&token=123'

Need on võtmed, mida server kasutab peab pakutavad väärtused:

Võti Väärtus Kommentaarid
REQUEST_METHOD 'GET'
SCRIPT_NAME '' serveri seadistus sõltub
PATH_INFO '/auth'
QUERY_STRING 'token=123'
CONTENT_TYPE ''
CONTENT_LENGTH ''
SERVER_NAME '127.0.0.1' serveri seadistus sõltub
SERVER_PORT '8000'
SERVER_PROTOCOL 'HTTP/1.1'
HTTP_(...) Kliendi pakutavad HTTP-päised
wsgi.version (1, 0) kahekordne WSGI versiooniga
wsgi.url_scheme 'http'
wsgi.input Failitaoline objekt
wsgi.errors Failitaoline objekt
wsgi.multithread False True kui server on mitmekeermeline
wsgi.multiprocess False True kui server töötab mitu protsessi
wsgi.run_once False True kui server eeldab, et see skript töötab ainult üks kord (nt CGI-keskkonnas)

Selle reegli erand on see, et kui üks neist võtmetest peaks olema tühi (nagu | ülaltoodud tabelis CONTENT_TYPE), siis saab need sõnastikust välja jätta ja eeldatakse, et need vastavad tühjale stringile.

wsgi.input ja wsgi.errors

Enamik environ võtmed on otsekohesed, kuid kaks neist väärivad veidi täpsustust: wsgi.input, mis peab sisaldama voogu koos kliendi päringukehaga ja wsgi.errors, kus rakendus teatab kõigist ilmnenud vigadest. Rakendusest wsgi.errors saadetud vead tavaliselt saadetakse serveri tõrglogi.

Need kaks võtit peavad sisaldama failitaolisi objekte; see tähendab objektid, mis pakuvad liideseid voogudeks lugemiseks või kirjutamiseks, täpselt nagu objekt, mille saame Pythonis faili või sokli avamisel. See võib esialgu tunduda keeruline, kuid õnneks annab Python meile selle käsitsemiseks häid tööriistu.

Esiteks, millistest voogudest me räägime? Vastavalt WSGI määratlusele wsgi.input ja wsgi.errors peab käsitsema bytes objektid Python 3-s ja str objektid Python 2-s. Mõlemal juhul, kui soovime kasutada mälus olevat puhvrit andmete edastamiseks või hankimiseks WSGI-liidese kaudu, võime kasutada klassi io.BytesIO

Näiteks kui kirjutame WSGI-serverit, võiksime taotlusekeha rakendusele pakkuda järgmiselt:

  • Pythoni 2.7 jaoks
import io ... request_data = 'some request body' environ['wsgi.input'] = io.BytesIO(request_data)
  • Pythoni 3.5 jaoks
import io ... request_data = 'some request body'.encode('utf-8') # bytes object environ['wsgi.input'] = io.BytesIO(request_data)

Rakenduse poolel, kui me sooviksime saadud voo sisendi stringiks muuta, tahaksime kirjutada midagi sellist:

  • Pythoni 2.7 jaoks
readstr = environ['wsgi.input'].read() # returns str object
  • Pythoni 3.5 jaoks
readbytes = environ['wsgi.input'].read() # returns bytes object readstr = readbytes.decode('utf-8') # returns str object

wsgi.errors voogu tuleks kasutada rakenduse tõrgetest serverisse teatamiseks ja read tuleks lõpetada tähega Veebiserver peaks hoolitsema selle eest, et süsteem teisendataks teisele reale.

Rakenduse helistatav start_response Argument

start_response argument peab olema kutsutav kahe nõutava argumendiga, nimelt status ja headers ning üks valikuline argument exc_info. Enne kui mõni kehaosa veebiserverisse tagasi saadetakse, peab rakendus sellele helistama.

Esimeses rakenduse näites selle artikli alguses oleme vastuse põhiosa tagastanud loendina ja seega pole meil võimalik kontrollida, millal loend uuesti tehakse. Seetõttu pidime helistama start_response enne loendi tagastamist.

Teises oleme helistanud start_response vahetult enne reaktsioonikeha esimese (ja antud juhul ainsa) tüki saamist. Mõlemad viisid kehtivad WSGI spetsifikatsioonides.

Veebiserveri poolelt helistatakse start_response ei peaks tegelikult päiseid kliendile saatma, vaid lükake seda edasi, kuni vastusekehas on vähemalt üks tühi bytesting, mis kliendile tagasi saadetakse. See arhitektuur võimaldab vigadest õigesti teatada kuni rakenduse viimase võimaliku hetkeni.

status Argument start_response

status argument edastati start_response -le tagasihelistamine peab olema string, mis koosneb HTTP olekukoodist ja kirjeldusest, eraldatuna ühe tühikuga. Kehtivad näited on: '200 OK' või '404 Not Found'.

headers Argument start_response

headers argument edastati start_response -le tagasihelistamine peab olema Python list / _ + _ | s, kusjuures iga tupel on moodustatud tuple. Nii päise nimi kui ka väärtus peavad olema stringid (olenemata Pythoni versioonist). See on haruldane näide, kus tüüp on oluline, kuna seda nõuab WSGI spetsifikatsioon.

Siin on sobiv näide selle kohta, mida (header_name, header_value) argument võib välja näha:

milleks Adobe kogemuste disaini kasutatakse
header

HTTP-päised ei erista suurtähti ja kui me kirjutame WSGI-ga ühilduvat veebiserverit, on see, mida nende päiste kontrollimisel arvestada. Samuti ei peaks rakenduse esitatud päiste loend olema täielik. Enne vastuse kliendile saatmist on serveri kohustus tagada, et kõik vajalikud HTTP-päised oleksid olemas, täites kõik päised, mida rakendus ei paku.

response_body = json.dumps(data).encode('utf-8') headers = [('Content-Type', 'application/json'), ('Content-Length', str(len(response_body))] Argument exc_info

start_response tagasihelistamine peaks toetama kolmandat argumenti start_response, mida kasutatakse tõrgete käsitlemisel. Selle argumendi õige kasutamine ja rakendamine on tootmise veebiserverite ja -rakenduste jaoks ülioluline, kuid jääb selle artikli reguleerimisalast välja.

Lisateavet selle kohta leiate WSGI spetsifikatsioonist, siin .

exc_info Tagastusväärtus - start_response Helista tagasi

Tagasiühilduvuse tagamiseks peaksid WSGI-d rakendavad veebiserverid tagastama write helistatav. See tagasihelistamine peaks võimaldama rakendusel kirjutada kehavastuse andmed otse kliendile tagasi, selle asemel, et need iteraatori kaudu serverile edastada.

Hoolimata oma olemasolust, on see liides ära ja uued rakendused peaksid selle kasutamisest hoiduma.

Reageeriva keha loomine

WSGI-d rakendavad rakendused peaksid reageeriva keha genereerima, tagastades korduva objekti. Enamiku rakenduste puhul pole vastuse sisu eriti suur ja mahub kergesti serveri mällu. Sel juhul on kõige tõhusam viis selle saatmiseks korraga, ühe elemendiga iterable. Erijuhtudel, kui kogu keha mällu laadimine on teostamatu, võib rakendus selle korduva liidese kaudu selle osaliselt tagastada.

Siin on Python 2 ja Python 3 WSGI vahel vaid väike erinevus: Python 3-s esindab vastuskeha write esemed; Python 2-s on selle õige tüüp bytes.

UTF-8 stringide teisendamine str -ks või bytes on lihtne ülesanne:

  • Python 3.5:
str
  • Python 2.7:
body = 'unicode stuff'.encode('utf-8')

Kui soovite rohkem teada saada Python 2 unicode'i ja bytestringi käitlemise kohta, on siin kena õpetus Youtube .

WSGI-d rakendavad veebiserverid peaksid toetama ka body = u'unicode stuff'.encode('utf-8') tagasihelistamine tagurpidi ühilduvuse tagamiseks, nagu eespool kirjeldatud.

Rakenduse testimine ilma veebiserverita

Selle lihtsa liidese mõistmisega saame hõlpsasti luua skripte oma rakenduste testimiseks, ilma et peaksime tegelikult serverit käivitama.

Võtke näiteks see väike skript:

write

Sel moel võime näiteks initsialiseerida mõned testiandmed ja mõnitada moodulid oma rakendusse ning teha from io import BytesIO def get(app, path = '/', query = ''): response_status = [] response_headers = [] def start_response(status, headers): status = status.split(' ', 1) response_status.append((int(status[0]), status[1])) response_headers.append(dict(headers)) environ = { 'HTTP_ACCEPT': '*/*', 'HTTP_HOST': '127.0.0.1:8000', 'HTTP_USER_AGENT': 'TestAgent/1.0', 'PATH_INFO': path, 'QUERY_STRING': query, 'REQUEST_METHOD': 'GET', 'SERVER_NAME': '127.0.0.1', 'SERVER_PORT': '8000', 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'TestServer/1.0', 'wsgi.errors': BytesIO(b''), 'wsgi.input': BytesIO(b''), 'wsgi.multiprocess': False, 'wsgi.multithread': False, 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.version': (1, 0), } response_body = app(environ, start_response) merged_body = ''.join((x.decode('utf-8') for x in response_body)) if hasattr(response_body, 'close'): response_body.close() return {'status': response_status[0], 'headers': response_headers[0], 'body': merged_body} helistab, et testida, kas see vastab sellele. Näeme, et see pole tegelik veebiserver, vaid liidestub meie rakendusega võrreldaval viisil, pakkudes rakendusele GET tagasihelistamine ja sõnastik meie keskkonnamuutujatega. Taotluse lõpus kulutab ta vastuse keha iteraatori ja tagastab stringi kogu sisuga. Sarnaseid meetodeid (või üldisi) saab luua erinevat tüüpi HTTP-päringute jaoks.

Pakkima

WSGI on peaaegu iga Pythoni veebiraamistiku kriitiline osa.

Selles artiklis ei ole me käsitlenud seda, kuidas WSGI failide üleslaadimisega tegeleb, kuna seda võiks pidada 'täpsemaks' funktsiooniks, mis ei sobi sissejuhatava artikli jaoks. Kui soovite selle kohta rohkem teada saada, vaadake Failide käitlemist käsitlev jaotis PEP-3333 .

Loodan, et see artikkel on kasulik, et aidata paremini mõista, kuidas Python veebiserveritega suhtleb, ja võimaldab arendajatel seda liidest huvitaval ja loomingulisel viisil kasutada.

Tänusõnad

Tahaksin tänada oma toimetajat Nick McCrea selle artikli aitamise eest. Tema töö tõttu sai algtekst palju selgemaks ja mitmed vead ei jäänud parandamata.

Automatiseerimine seleenis: leheobjekti mudel ja lehevabrik

Tehnoloogia

Automatiseerimine seleenis: leheobjekti mudel ja lehevabrik
Kuidas läheneda finantsandmete visualiseerimisele

Kuidas läheneda finantsandmete visualiseerimisele

Finantsprotsessid

Lemmik Postitused
GraphQL-serveri loomine Laraveli abil
GraphQL-serveri loomine Laraveli abil
Lõplik juhend WordPressi pistikprogrammi loomiseks
Lõplik juhend WordPressi pistikprogrammi loomiseks
Kujundusprotsess: kas see on objektiivne või subjektiivne?
Kujundusprotsess: kas see on objektiivne või subjektiivne?
ICO-d, eksootika ja platvormid - siseringi vaatenurk riskikapitali tulevikule
ICO-d, eksootika ja platvormid - siseringi vaatenurk riskikapitali tulevikule
SaaS-i hinnamudelid - hinnastrateegia näited ja parimad tavad
SaaS-i hinnamudelid - hinnastrateegia näited ja parimad tavad
 
Näpunäited ja kaalutlused kirjatüübi valimisel (koos infograafikaga)
Näpunäited ja kaalutlused kirjatüübi valimisel (koos infograafikaga)
Võimaluste ring: sisemine pilk sellele, kuidas tipptalente meelitada ja hoida
Võimaluste ring: sisemine pilk sellele, kuidas tipptalente meelitada ja hoida
Täiustage oma UX-i disainiprotsessi - juhend prototüübi kujundamiseks
Täiustage oma UX-i disainiprotsessi - juhend prototüübi kujundamiseks
Projektisõitja: eraldiseisev ReSharper IDE
Projektisõitja: eraldiseisev ReSharper IDE
Sloveenia arendaja Ana Sustic võidab teise ApeeScape'i stipendiumi
Sloveenia arendaja Ana Sustic võidab teise ApeeScape'i stipendiumi
Lemmik Postitused
  • sissejuhatus agiilsesse projektijuhtimisse
  • kuidas kasutada vedrukarkassi
  • mis on c and s korporatsioon
  • muusikatööstus kasvab
  • c corp või s corp
  • mis on /c/
Kategooriad
  • Tulud Ja Kasv
  • Protsess Ja Tööriistad
  • Investorid Ja Rahastamine
  • Puldi Tõus
  • © 2022 | Kõik Õigused Kaitstud

    portaldacalheta.pt