処理要求ジャンゴ

ジャンゴrunseverに基づいて、

  • エントランス
    • python manage.pyののrunserverを実行します
      • 调用django.core.management.commands.runserver.Command.handle
      • 文件runserver.py(ジャンゴ/コア/管理/コマンド/ runserver.py)
  • TCPサーバーを起動
    • 上記ハンドルからdjango.core.servers.basehttp.runを入力します
    # 其中 server_cls 为 WSGIServer
    def run(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
      # wsgi_handler 为 settings.WSGI_APPLICATION 一般为 product_name/wsgi.py 中的 application
      httpd.set_app(wsgi_handler) # httpd_cls.application = application 在后面 get_app 方法中会获取到
      httpd.serve_forever()
  • server_foreverを入力します。
# socketserver.BaseServer.serve_forever
    def serve_forever(self, poll_interval=0.5):
        """Handle one request at a time until shutdown.

        Polls for shutdown every poll_interval seconds. Ignores
        self.timeout. If you need to do periodic tasks, do them in
        another thread.
        """
        self.__is_shut_down.clear()
        try:
            # XXX: Consider using another file descriptor or connecting to the
            # socket to wake this up instead of polling. Polling reduces our
            # responsiveness to a shutdown request and wastes cpu at all other
            # times.
            with _ServerSelector() as selector:
                selector.register(self, selectors.EVENT_READ)

                while not self.__shutdown_request:
                    ready = selector.select(poll_interval)
                    # bpo-35017: shutdown() called during select(), exit immediately.
                    if self.__shutdown_request:
                        break
                    if ready:
                        self._handle_request_noblock()

                    self.service_actions()
        finally:
            self.__shutdown_request = False
            self.__is_shut_down.set()
  • 次に、(self._handle_request_noblockを入力してください)
# socketserver.BaseServer._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:
            request, client_address = self.get_request()
        except OSError:
            return
        if self.verify_request(request, client_address):
            try:
                self.process_request(request, client_address)
            except Exception:
                self.handle_error(request, client_address)
                self.shutdown_request(request)
            except:
                self.shutdown_request(request)
                raise
        else:
            self.shutdown_request(request)

前記だけ要求ソケットオブジェクトである要求、client_address = self.get_request()、

# socketserver.TCPServer.get_request
    def get_request(self):
        """Get the request and client address from the socket.

        May be overridden.

        """
        return self.socket.accept()
  • 処理要求self.process_request(リクエスト、client_address)
# socketserver.BaseServer.process_request
    def process_request(self, request, client_address):
        """Call finish_request.

        Overridden by ForkingMixIn and ThreadingMixIn.

        """
        self.finish_request(request, client_address)
        self.shutdown_request(request)
  • 要求self.finish_requestを完了します(リクエスト、client_address)
# socketserver.BaseServer.finish_request
    def finish_request(self, request, client_address):
        """Finish one request by instantiating RequestHandlerClass."""
        self.RequestHandlerClass(request, client_address, self)

前記RequestHandlerClassはWSGIRequestHandler(django.core.servers.basehttp.WSGIRequestHandler)です
注:この時間は、要求だけソケットオブジェクトである<クラスのsocket.socket '>

  • ハンドラをインスタンス化socketserver.BaseRequestHandler
# socketserver.BaseRequestHandler
    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()

どのself.handle

# django.core.servers.basehttp.WSGIRequestHandler.handle
    def handle(self):
        self.close_connection = True
        self.handle_one_request()
        while not self.close_connection:
            self.handle_one_request()
        try:
            self.connection.shutdown(socket.SHUT_WR)
        except (socket.error, AttributeError):
            pass
  • )(リクエストから情報を取得Self.handle_one_request
# django.core.servers.basehttp.WSGIRequestHandler.handle_one_request
    def handle_one_request(self):
        """Copy of WSGIRequestHandler.handle() but with different ServerHandler"""
        self.raw_requestline = self.rfile.readline(65537)
        if len(self.raw_requestline) > 65536:
            self.requestline = ''
            self.request_version = ''
            self.command = ''
            self.send_error(414)
            return

        if not self.parse_request():  # An error code has been sent, just exit
            return

        handler = ServerHandler(
            self.rfile, self.wfile, self.get_stderr(), self.get_environ()
        )
        handler.request_handler = self      # backpointer for logging & connection closing
        handler.run(self.server.get_app())  # 对应上面的 set_app

ServerHandlerのインスタンス化は、特別な処理を行いません。ここで

# django.core.servers.basehttp.ServerHandler
pass

ラン

# wsgiref.handlers.BaseHandler.run
# application 则是上面的 get_app 拿到的结果
    def run(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()
        except:
            try:
                self.handle_error()
            except:
                # If we get an error handling an error, just give up already!
                self.close()
                raise   # ...and let the actual server figure it out.

コールハンドラ __call__

  • 上記のアプリケーションは、実際に製品/ wsgi.pyは最終的にアプリケーションがWSGIHandlerの一例である持っています
# django.core.handlers.wsgi.WSGIHandler
class WSGIHandler(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_started 信号
        request = self.request_class(environ) # 实例化 WSGIRequest 得到 django 中 view 中真实的 request
        response = self.get_response(request) # 获取 response 会进入 middleware

        response._handler_class = self.__class__

        status = '%d %s' % (response.status_code, response.reason_phrase)
        response_headers = list(response.items())
        for c in response.cookies.values():
            response_headers.append(('Set-Cookie', c.output(header='')))
        start_response(status, response_headers)
        if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'):
            response = environ['wsgi.file_wrapper'](response.file_to_stream)
        return response
  • リクエストの例
# django.core.handlers.wsgi.WSGIRequest
pass
  • 応答を取得
# django.core.handlers.base.BaseHandler.get_response
    def get_response(self, request):
        """Return an HttpResponse object for the given HttpRequest."""
        # Setup default url resolver for this thread
        set_urlconf(settings.ROOT_URLCONF)

        response = self._middleware_chain(request)

        response._closable_objects.append(request)

        # If the exception handler returns a TemplateResponse that has not
        # been rendered, force it to be rendered.
        if not getattr(response, 'is_rendered', True) and callable(getattr(response, 'render', None)):
            response = response.render()

        if response.status_code >= 400:
            log_response(
                '%s: %s', response.reason_phrase, request.path,
                response=response,
                request=request,
            )

        return response

その後に戻って実行します

  • 次self.finish_responseに注意()
# wsgiref.handlers.BaseHandler.finish_response
    def finish_response(self):
        """Send any iterable data, then close self and the iterable

        Subclasses intended for use in asynchronous servers will
        want to redefine this method, such that it sets up callbacks
        in the event loop to iterate over the data, and to call
        'self.close()' once the response is finished.
        """
        try:
            if not self.result_is_file() or not self.sendfile():
                for data in self.result:
                    self.write(data)
                self.finish_content()
        finally:
            self.close()

# 其中  self.write
# wsgiref.handlers.BaseHandler.write
    def write(self, data):
        """'write()' callable as specified by PEP 3333"""

        assert type(data) is bytes, \
            "write() argument must be a bytes instance"

        if not self.status:
            raise AssertionError("write() before start_response()")

        elif not self.headers_sent:
            # Before the first output, send the stored headers
            self.bytes_sent = len(data)    # make sure we know content-length
            self.send_headers()
        else:
            self.bytes_sent += len(data)

        # XXX check Content-Length and truncate if too many bytes written?
        self._write(data)
        self._flush()

# 其中 self._write
# wsgiref.handlers.SimpleHandler._write
    def _write(self,data):
        result = self.stdout.write(data)
        if result is None or result == len(data):
            return
        from warnings import warn
        warn("SimpleHandler.stdout.write() should not do partial writes",
            DeprecationWarning)
        while True:
            data = data[result:]
            if not data:
                break
            result = self.stdout.write(data)

# 其中 result = self.stdout.write(data)
    def write(self, b):
        self._sock.sendall(b)
        with memoryview(b) as view:
            return view.nbytes

おすすめ

転載: www.cnblogs.com/ywhyme/p/11357496.html