Ich habe versucht, den Code von Bottle, einem Webframework von Python, zu lesen. Der Quellcode für Bottle ist in Bottle.py zusammengefasst, daher sollten Sie diese Datei lesen.
Klicken Sie hier für GitHub. https://github.com/bottlepy/bottle
Der unten angegebene Code stammt von Bottle.py und enthält nur die erforderlichen Teile. Außerdem füge ich an einigen Stellen Kommentare hinzu.
Es ist schwierig, den Details von Anfang an zu folgen, daher möchte ich zuerst den Gesamtfluss erfassen.
Ich möchte der Quelle in der Reihenfolge vom Start folgen. Starten Sie die Flasche beispielsweise wie folgt gemäß der Dokumentation.
from bottle import route, run, template
@route('/hello/<name>')
def index(name):
return template('<b>Hello {{name}}</b>!', name=name)
run(host='localhost', port=8080)
Beginnen wir mit run ()
.
Auch für alle Fälle ist der Quellcode (meistens) kaputt und in Anführungszeichen gesetzt.
bottle.py
def run(app=None,
server='wsgiref',
host='127.0.0.1',
port=8080,
interval=1,
reloader=False,
quiet=False,
plugins=None,
debug=None,
config=None, **kargs):
app = app or default_app()
if server in server_names:
server = server_names.get(server)
if isinstance(server, basestring):
server = load(server)
if isinstance(server, type):
server = server(host=host, port=port, **kargs)
if not isinstance(server, ServerAdapter):
raise ValueError("Unknown or unsupported server: %r" % server)
if reloader:
lockfile = os.environ.get('BOTTLE_LOCKFILE')
bgcheck = FileCheckerThread(lockfile, interval)
with bgcheck:
server.run(app)
if bgcheck.status == 'reload':
sys.exit(3)
else:
server.run(app)
Zusamenfassend
app = app or default_app() #Der Standardwert ist App=None
server = server_names.get(server) #Der Standardwert ist Server='wsgiref'
server.run(app)
Korrekt.
Schauen wir uns zunächst die Definition von default_app ()
in der ersten Zeile an.
Der Definitionsteil ist
apps = app = default_app = AppStack()
damit,
bottle.py
class AppStack(list):
""" A stack-like list. Calling it returns the head of the stack. """
def __call__(self):
""" Return the current default application. """
return self.default
def push(self, value=None):
""" Add a new :class:`Bottle` instance to the stack """
if not isinstance(value, Bottle):
value = Bottle()
self.append(value)
return value
new_app = push
@property
def default(self):
try:
return self[-1]
except IndexError:
return self.push()
Aha. AppStack erbt von der Liste. Von der Seite, die "AppStack ()" ("Server") verwendet, ist die Methode "call" wichtig.
Um die Überprüfung der Aufrufmethode zusammenzufassen:
app = AppStack()
app()
Es scheint, dass eine "Bottle" -Instanz zurückgegeben wird (wenn dies das Standardargument ist). Gleichzeitig ist es ein Mechanismus, um es als Liste zu akkumulieren.
Ich würde gerne die Quelle der "Flasche" -Klasse zusammenstellen, aber wie der Name schon sagt, ist dies der Kern von "Flasche" und lang. Erstens ist die AppStack-Instanz
server.run(app)
Es wird als Argument an die run-Methode des Servers übergeben und sollte danach "app ()" heißen. Überprüfen wir also zuerst "server".
Ein wenig zurückblicken,
app = app or default_app() #Der Standardwert ist App=None
server = server_names.get(server) #Der Standardwert ist Server='wsgiref'
server.run(app)
Die Geschichte des Versuchs herauszufinden, wer der "Server" in dem Teil von definiert hat.
bottle.py
server_names = {
'cgi': CGIServer,
'flup': FlupFCGIServer,
'wsgiref': WSGIRefServer, #Dies ist die Standardeinstellung
'waitress': WaitressServer,
#Folgendes wird weggelassen
}
Es ist ein Wörterbuch, und jeder Wert erbt die Klasse "ServerAdapter". Da dies ein "nur übergeordnetes Formular" ist, gehe ich plötzlich zur Klasse "WSGIRefServer".
bottle.py
class WSGIRefServer(ServerAdapter):
def run(self, app): # pragma: no cover
from wsgiref.simple_server import make_server
from wsgiref.simple_server import WSGIRequestHandler, WSGIServer
import socket
server_cls = self.options.get('server_class', WSGIServer)
self.srv = make_server(self.host, self.port, app, server_cls,
handler_cls)
self.port = self.srv.server_port # update port actual port (0 means random)
try:
self.srv.serve_forever()
except KeyboardInterrupt:
self.srv.server_close() # Prevent ResourceWarning: unclosed socket
raise
Das an app.ser.run () übergebene app = AppStack ()
wird an die Funktion make_server
übergeben.
Die Funktion make_server
selbst stammt aus der Python-Standardbibliothek wsgiref
.
https://docs.python.org/ja/3/library/wsgiref.html
Die Webserver-Gateway-Schnittstelle (WSGI) ist eine Standardschnittstelle zwischen Webserver-Software und in Python geschriebenen Webanwendungen. Mit einer Standardschnittstelle können Anwendungen, die WSGI unterstützen, auf verschiedenen Webservern problemlos verwendet werden.
Schauen wir uns also das Beispiel in der wsgiref-Dokumentation an.
from wsgiref.util import setup_testing_defaults
from wsgiref.simple_server import make_server
def simple_app(environ, start_response):
setup_testing_defaults(environ)
status = '200 OK'
headers = [('Content-type', 'text/plain')]
start_response(status, headers)
ret = ["%s: %s\n" % (key, value)
for key, value in environ.iteritems()]
return ret
httpd = make_server('', 8000, simple_app)
print "Serving on port 8000..."
httpd.serve_forever()
simple_app
-Funktion im Beispiel) als drittes Argument für die make_server
-Funktion!
-Dann können Sie, wenn eine Anfrage eingeht, diese Funktion bearbeiten lassen!
-Vorbereiten Sie jedoch zwei Argumente (environ, start_response)
!Korrekt.
Rückblickend auf die bisherigen Quellen war diese Funktion (simple_app
im Beispiel ) Bottle ()
.
Es ist eine Instanz, keine Funktion!
aber es ist okay!
Wenn Sie eine __call__
Instanz haben, können Sie sie wie eine Funktion aufrufen!
Es scheint langweilig zu sein, aber wenn Sie es organisieren, ist es ein Beispiel
simple_app(environ, start_response)
Die auszuführende Handlung ist
Bottle()(environ, start_response)
Entspricht der Ausführung.
Das ist </ b>
Es scheint offensichtlich, aber die Flascheninstanz ist für die eigentliche Verarbeitung verantwortlich </ b>
Ich fand heraus.
Tatsächlich
bottle.py
class Bottle(object):
def __call__(self, environ, start_response):
Ist definiert.
Es war so lange.
Die Klasse "Flasche" sollte [Weiter] sein (https://qiita.com/nyancook/items/1181597a10f8c4481a56).
"Bottle ()" wird als Argument an die Funktion "make_server" der Bibliothek "wsgiref" übergeben und ist für die eigentliche Verarbeitung verantwortlich.
Recommended Posts