J'ai essayé de lire le code de Bottle, un framework web de Python. Le code source de Bottle est agrégé dans bottle.py, vous devriez donc lire ce fichier.
Cliquez ici pour GitHub. https://github.com/bottlepy/bottle
Le code cité ci-dessous provient de bottle.py avec uniquement les pièces nécessaires. De plus, j'ajoute des commentaires par endroits.
Il est difficile de suivre les détails depuis le début, je voudrais donc d'abord saisir le flux global.
Je voudrais suivre la source dans l'ordre depuis le démarrage. Démarrez Bottle comme suit, par exemple, conformément à la documentation.
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)
Commençons par run ()
.
Encore une fois, juste au cas où, le code source est (principalement) cassé et cité.
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)
en bref
app = app or default_app() #La valeur par défaut est app=None
server = server_names.get(server) #La valeur par défaut est le serveur='wsgiref'
server.run(app)
C'est vrai.
Jetons d'abord un œil à la définition de default_app ()
sur la première ligne.
La partie définition est
apps = app = default_app = AppStack()
alors,
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()
Je vois. AppStack hérite de la liste.
Du côté qui utilise ʻAppStack () (
server), l'important est la méthode
call`.
Pour résumer l'examen de la méthode d'appel,
app = AppStack()
app()
Renvoie une instance de Bottle
(avec des arguments par défaut).
En même temps, c'est un mécanisme pour l'accumuler sous forme de liste.
J'aimerais rassembler la source de la classe Bottle
, mais comme son nom l'indique, c'est le cœur de Bottle et c'est long.
En premier lieu, l'instance ʻAppStack` est
server.run(app)
Il est passé comme argument à la méthode run du serveur, et il devrait être appelé ʻapp () après cela, donc vérifions d'abord
server`.
En regardant un peu en arrière,
app = app or default_app() #La valeur par défaut est app=None
server = server_names.get(server) #La valeur par défaut est le serveur='wsgiref'
server.run(app)
L'histoire d'essayer de découvrir qui le serveur
a défini dans la partie de.
bottle.py
server_names = {
'cgi': CGIServer,
'flup': FlupFCGIServer,
'wsgiref': WSGIRefServer, #C'est la valeur par défaut
'waitress': WaitressServer,
#Ce qui suit est omis
}
C'est un dictionnaire, et chaque valeur hérite de la classe ServerAdapter
. Comme il s'agit d'un "parent de formulaire uniquement", je vais soudainement à la classe 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
ʻApp = AppStack () passé à
server.run () est passé à la fonction
make_server. La fonction
make_server elle-même provient de la bibliothèque standard python
wsgiref`.
https://docs.python.org/ja/3/library/wsgiref.html
L'interface de passerelle de serveur Web (WSGI) est une interface standard entre le logiciel de serveur Web et les applications Web écrites en Python. Une interface standard facilite l'utilisation d'applications prenant en charge WSGI sur un certain nombre de serveurs Web différents.
Jetons donc un œil à l'exemple dans la documentation wsgiref
.
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()
-Passez la fonction que vous avez définie (fonction simple_app
dans l'exemple) comme troisième argument de la fonction make_server
!
-Ensuite, lorsqu'une requête arrive, vous pouvez laisser cette fonction la gérer!
-Cependant, préparez deux arguments (environ, start_response)
!
C'est vrai.
Donc, en regardant les sources jusqu'à présent, cette fonction (simple_app
dans l'exemple) était Bottle ()
.
C'est une instance, pas une fonction!
mais c'est d'accord!
Si vous avez une instance __call__
, vous pouvez l'appeler comme une fonction!
Cela semble fastidieux, mais si vous l'organisez, c'est un échantillon
simple_app(environ, start_response)
L'acte à exécuter est
Bottle()(environ, start_response)
Équivaut à être exécuté.
C'est-à-dire </ b>
Cela semble évident, mais l'instance Bottle est responsable du traitement réel </ b>
J'ai découvert.
Réellement
bottle.py
class Bottle(object):
def __call__(self, environ, start_response):
Est défini.
C'était si long.
La classe Bottle
doit être Next.
Bottle ()
est passé comme argument à la fonction make_server
de la bibliothèque wsgiref
, et ceci est responsable du traitement réel.
Recommended Posts