#django\core\management\commands\runserver.pydefhandle(self,*args,**options):...
self.run(**options)defrun(self,**options):"""Run the server, using the autoreloader if needed."""
use_reloader = options['use_reloader']if use_reloader:
autoreload.run_with_reloader(self.inner_run,**options)else:
self.inner_run(None,**options)definner_run(self,*args,**options):# If an exception was silenced in ManagementUtility.execute in order# to be raised in the child process, raise it now.
autoreload.raise_last_exception()
threading = options['use_threading']# 'shutdown_message' is a stealth option.
shutdown_message = options.get('shutdown_message','')
quit_command ='CTRL-BREAK'if sys.platform =='win32'else'CONTROL-C'
self.stdout.write("Performing system checks...\n\n")
self.check(display_num_errors=True)...try:
handler = self.get_handler(*args,**options)
run(self.addr,int(self.port), handler,
ipv6=self.use_ipv6, threading=threading, server_cls=self.server_cls)except socket.error as e:# Use helpful error messages instead of ugly tracebacks.
ERRORS ={
errno.EACCES:"You don't have permission to access that port.",
errno.EADDRINUSE:"That port is already in use.",
errno.EADDRNOTAVAIL:"That IP address can't be assigned to.",}...
defget_handler(self,*args,**options):"""Return the default WSGI handler for the runner."""return get_internal_wsgi_application()# core\servers\basehttp.pydefget_internal_wsgi_application():"""
Load and return the WSGI application as configured by the user in
``settings.WSGI_APPLICATION``. With the default ``startproject`` layout,
this will be the ``application`` object in ``projectname/wsgi.py``.
This function, and the ``WSGI_APPLICATION`` setting itself, are only useful
for Django's internal server (runserver); external WSGI servers should just
be configured to point to the correct application object directly.
If settings.WSGI_APPLICATION is not set (is ``None``), return
whatever ``django.core.wsgi.get_wsgi_application`` returns.
"""from django.conf import settings
app_path =getattr(settings,'WSGI_APPLICATION')if app_path isNone:return get_wsgi_application()# core\wsgi.pydefget_wsgi_application():"""
The public interface to Django's WSGI support. Return a WSGI callable.
Avoids making django.core.handlers.WSGIHandler a public API, in case the
internal WSGI implementation changes or moves in the future.
"""
django.setup(set_prefix=False)return WSGIHandler()#core\handlers\wsgi.pyclassWSGIHandler(base.BaseHandler):
request_class = WSGIRequest
def__init__(self,*args,**kwargs):super().__init__(*args,**kwargs)
self.load_middleware()def__call__(self, environ, start_response):
set_script_prefix(get_script_name(environ))
signals.request_started.send(sender=self.__class__, environ=environ)
request = self.request_class(environ)
response = self.get_response(request)
response._handler_class = self.__class__
status ='%d %s'%(response.status_code, response.reason_phrase)
response_headers =[*response.items(),*(('Set-Cookie', c.output(header=''))for c in response.cookies.values()),]
start_response(status, response_headers)ifgetattr(response,'file_to_stream',None)isnotNoneand environ.get('wsgi.file_wrapper'):
response = environ['wsgi.file_wrapper'](response.file_to_stream)return response
defrun(addr, port, wsgi_handler, ipv6=False, threading=False, server_cls=WSGIServer):
server_address =(addr, port)if threading:
httpd_cls =type('WSGIServer',(socketserver.ThreadingMixIn, server_cls),{})else:
httpd_cls = server_cls
httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)if threading:# ThreadingMixIn.daemon_threads indicates how threads will behave on an# abrupt shutdown; like quitting the server by the user or restarting# by the auto-reloader. True means the server will not wait for thread# termination before it quits. This will make auto-reloader faster# and will prevent the need to kill the server manually if a thread# isn't terminating correctly.
httpd.daemon_threads =True
httpd.set_app(wsgi_handler)
httpd.serve_forever()
处理请求
当发现有请求后,就调用 _handle_request_noblock 进行处理:
# C:\Python36\Lib\socketserver.pydefserve_forever(self, poll_interval=0.5):"""Handle one request at a time until shutdown.
处理一个 http 请求直到关闭
Polls for shutdown every poll_interval seconds. Ignores
self.timeout. If you need to do periodic tasks, do them in
another thread.
"""# __is_shut_down为一个初始化的threading.Event()的句柄,用于线程间通信,clear()将标识设置为false
self.__is_shut_down.clear()...whilenot self.__shutdown_request:# 一个封装好了的select函数,超时时间 0.5 s
ready = selector.select(poll_interval)if ready:# 调用 _handle_request_noblock 做处理:
self._handle_request_noblock()...finally:
self.__shutdown_request =False#set将标识重置为true
self.__is_shut_down.set()
_handle_request_noblock
def_handle_request_noblock(self):"""Handle one request, without blocking.
I assume that selector.select() has returned that the socket is
readable before this function was called, so there should be no risk of
blocking in get_request().
"""try:# 返回请求句柄,客户端地址,get_request()中调用了self.socket.accept()来实现客户端的连接
request, client_address = self.get_request()except OSError:return# 验证请求合法性if self.verify_request(request, client_address):try:# 真正的处理连接请求的地方,调用了self.process_request(request, client_address)
self.process_request(request, client_address)...
classBaseRequestHandler:"""Base class for request handler classes.
This class is instantiated for each request to be handled. The
constructor sets the instance variables request, client_address
and server, and then calls the handle() method. To implement a
specific service, all you need to do is to derive a class which
defines a handle() method.
The handle() method can find the request as self.request, the
client address as self.client_address, and the server (in case it
needs access to per-server information) as self.server. Since a
separate instance is created for each request, the handle() method
can define other arbitrary instance variables.
"""def__init__(self, request, client_address, server):
self.request = request
self.client_address = client_address
self.server = server
self.setup()try:
self.handle()finally:
self.finish()defsetup(self):passdefhandle(self):passdeffinish(self):pass
defrun(self, application):"""Invoke the application"""# Note to self: don't move the close()! Asynchronous servers shouldn't# call close() from finish_response(), so if you close() anywhere but# the double-error branch here, you'll break asynchronous servers by# prematurely closing. Async servers must return from 'run()' without# closing if there might still be output to iterate over.try:
self.setup_environ()
self.result = application(self.environ, self.start_response)
self.finish_response()...#core\handlers\wsgi.pyclassWSGIHandler(base.BaseHandler):
request_class = WSGIRequest
def__call__(self, environ, start_response):
set_script_prefix(get_script_name(environ))
signals.request_started.send(sender=self.__class__, environ=environ)
request = self.request_class(environ)
response = self.get_response(request)...return response