flask 请求上下文源码(转)

本篇阅读目录

  • 一、flask请求上下文源码解读
  • 二、http聊天室(单聊/群聊)- 基于gevent-websocket

回到顶部

转:https://www.cnblogs.com/li-li/p/10252058.html#main

一、flask请求上下文源码解读

  通过上篇源码分析,我们知道了有请求发来的时候就执行了app(Flask的实例化对象)的__call__方法,而__call__方法返回了app的wsgi_app(environ, start_response)方法的执行结果,而wsgi_app方法中有这样一句话:ctx = self.request_context(environ),还分析除了ctx是RequestContext类的实例化对象,而且ctx中含有有本次请求的request对象和session对象。

  接下来我们重点分析flask是如何做到把request对象当成全局变量,而又保证了数据安全,即请求信息互不影响的。

1、flask请求上文源码解读

  上篇我们分析到了如何得到RequestContext实例化对象ctx,接下来ctx对象执行push方法,如下:

  RequestContext类中的push方法源码如下:

  _request_ctx_stack是LocalStack类的实例化对象:

  

  LocalStack类中的__init__方法如下:

  Local类的__init__方法如下:

  get_ident是Local类所在文件中导入的一个方法名,该方法执行后会得到线程或协程ID,如下:

  LocalStack类中的top是一个属性方法,源码如下:

  下一步Local类中的__getattr__方法源码如下:

  到此,分析得出top = _request_ctx_stack.top中的top为None。

  接下来分析 _request_ctx_stack.push(self)做了什么?LocalStack类中的push方法源码如下:

  Local类中的__setattr__方法源码如下:

  因为rv.append(obj),所以最后LocalStack对象,即_request_ctx_stack对象字典化后如下:

  {‘_local‘:{‘__storage__‘:{9527:{stack:[ctx]}}, ‘__ident_func__‘:get_ident}}
  # 说明:9527假设是获取到的线程或者协程号,ctx包含request对象和session对象。

  到此,flask请求上文结束,也就是完成了将一个request和session对象存储到某个地方。

2、下文

  我们知道flask的request对象和session对象是全局变量,上文已经解读了如何存储。接下来解读如何在保证数据安全的情况下取出来,即只取到自己的请求信息而非其他人的。

  我们还知道request对象中存储了很多信息,如request.method存储请求方式、request.json存储json标准字符串等等。下面以request.method为例,分析如何得到请求方式信息。

  导入request方式如下:

  from flask import request

  源码如下:

  LocalProxy类的__init__方法如下:

  偏函数中的原函数_lookup_req_object源码如下:

  当执行request.method的时候,执行LocalProxy的__getattr__方法,源码如下:

  查看类LocalProxy中的_get_current_object方法是如何得到本次请求的request对象,源码如下:

  至此,我们已经分析出了如何得到本次请求的request对象,从而取出request对象中的相关信息。

回到顶部

二、http聊天室(单聊/群聊)- 基于gevent-websocket

1、准备知识

  http协议特点:短连接,无状态保存;

  轮询:前后端一秒交互多次,压力极大,并且消耗带宽,资源浪费极其严重;

  长轮询:即让服务器保存我的一个连接状态,用于快速传递消息,节省带宽,释放压力,数据实时性强;

  长连接:服务端及客户端节省极大的资源,能保证数据实时性;

  带宽:1Mbps  = 128KB/s

2、http聊天室

  准备工作:下载gevent-websocket模块

?


1

pip3 install gevent-websocket

  代码示例:

  manage.py代码:

  from flask import Flask, request, render_template
  from geventwebsocket.handler import WebSocketHandler
  from geventwebsocket.websocket import WebSocket  # 提示用
  from gevent.pywsgi import WSGIServer
  import json

  app = Flask(__name__)

  user_socket_dict = {}   # 用户字典

  @app.route(‘/ws/<username>‘)
  def ws(username):
    print(request.environ) # 有个wsgi.websocket,通过它可以发消息
    user_socket = request.environ.get(‘wsgi.websocket‘)  #type:WebSocket
    if user_socket:
      user_socket_dict[username] = user_socket
    print(user_socket_dict)
    while 1:
      msg = user_socket.receive()
      msg_dict = json.loads(msg)
      msg_dict[‘from_user‘] = username
      to_user = msg_dict.get(‘to_user‘)
      # chat = msg_dict.get(‘msg‘)
      u_socket = user_socket_dict.get(to_user)  #type:WebSocket
      u_socket.send(json.dumps(msg_dict))

  @app.route(‘/‘)
  def index():
    return render_template(‘ws.html‘)

  if __name__ == ‘__main__‘:
    http_serv = WSGIServer((‘0.0.0.0‘,9527), app, handler_class=WebSocketHandler)
    http_serv.server_forever()

  ws.html代码:

  <!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title</title>
  </head>
  <body>

    <input id="username"type="text"><button onclick="login()">登录聊天室</button>

    给<input id="to_user"type="text">

    <input id="msg"type="text"><button onclick="send_msg()">发送</button>

    <div id="chat_list"style="width:500px; height:500px; border:1px solid red;"></div>

  </body>

  <script type="text/javascript">

  var ws = null;   // 因其他函数也可能会用到ws,所以不能放在某一个函数中

  function login() {
    var username = document.getElementById(‘username‘).value;
    var ws = new WebSocket(‘ws://192.168.13.172:9527/ws‘+username);  // ws请求协议
    ws.onmessage = function (data) {
      console.log(data.data);
      var recv_msg = JSON.parse(data.data);
      var ptag = document.createElement(‘p‘);
      ptag.innerText = recv_msg.from_user + ‘:‘ + recv_msg.msg;
      document.getElementById(‘caht_list‘).appendChild(ptag)
    };
  }

  function send_msg() {
    var to_user = document.getElementById(‘to_user‘).value;
    var msg = document.getElementById(‘msg‘).value;
    var send_dict = {
      ‘to_user‘:to_user,
      ‘msg‘:msg
    };
    ws.send(JSON.stringify(send_dict));
  }

  </script>

  </html>

原文地址:https://www.cnblogs.com/kenD/p/10453056.html

时间: 2024-09-30 16:20:47

flask 请求上下文源码(转)的相关文章

Flask上下文源码分析(一)

flask中的上下文分两种,application context和request context,即应用上下文和请求上下文. 从名字上看,可能会有误解,认为应用上下文是一个应用的全局变量,所有请求都可以访问修改其中的内容:而请求上下文则是请求内可访问的内容. 但事实上,这两者并不是全局与局部的关系,它们都处于一个请求的局部中. 先说结论:每个请求的g都是独立的,并且在整个请求内都是可访问修改的. 下面来研究一下. 上下文类的定义: 上下文类定义在flask.ctx模块中 class AppCo

flask请求上下文 (转)

本篇阅读目录 一.flask中的CBV 二.werkzeug + 上下文初步解读 三.偏函数和线程安全 回到顶部 一.flask中的CBV 对比django中的CBV,我们来看一下flask中的CBV怎么实现? from flask import Flask, render_template, url_for, views app = Flask(__name__) class Login(views.MethodView): def get(self): print(url_for("my_l

Anroid-async-http封装网络请求框架源码分析

Android-async-http开源项目可以是我们轻松的获取网络数据或者向服务器发送数据,使用起来非常简单, 这个网络请求库是基于Apache HttpClient库之上的一个异步网络请求处理库,网络处理均基于Android的非UI线程,通过回调方法处理请求结果. 主要特点:处理异步Http请求,并通过匿名内部类处理回调结果,Http异步请求均位于非UI线程,不会阻塞UI操作,通过线程池处理并发请求处理文件上传.下载,响应结果自动打包JSON格式. 一, Android-async-http

Flask中session源码执行过程

1.面向对象补充知识metaclass 创建类就可以有两种方式: a.普通方式 1 class Foo(object): 2 3 def func(self): 4 print 'hello wupeiqi' b.特殊方式(type类的构造函数) 1 def func(self): 2 print 'hello wupeiqi' 3 4 Foo = type('Foo',(object,), {'func': func}) 5 #type第一个参数:类名 6 #type第二个参数:当前类的基类

Flask框架 —— session源码分析

目录 session源码分析 1.请求来了,执行__call__方法 2.__call__方法 3.调用__call__方法 3.1.ctx = self.request_context(environ) --- 得到空的session 3.2.ctx.push() --- 调用open_session方法 3.3.self.full_dispatch_request() --- 路由分发,执行函数,写入session session源码分析 1.请求来了,执行__call__方法 # 请求来了

Android网络框架OkHttp之get请求(源码初识)

概括 OkHttp现在很火呀.于是上个星期就一直在学习OkHttp框架,虽然说起来已经有点晚上手了,貌似是2013年就推出了.但是现在它版本更加稳定了呀.这不,说着说着,OkHttp3.3版本在这几天又发布了.以下以OkHttp3.2版本为准,没办法,上个星期看的时候还是以3.2为最新版本的.首先,我们要先了解一些背景,OkHttp这个框架是有Square公司推出的,进入官网.如果想看API,点击进入API.大概了解了OkHttp之后,我们应该知道OkHttp是一个网络框架,想想以前在开发中,网

Flask之wtforms源码分析

一.wtforms源码流程 1.实例化流程分析 1 # 源码流程 2 1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中: meta类读取到cls._wtforms_meta中 3 2. 执行构造方法 4 5 a. 循环cls._unbound_fields中的字段,并执行字段的bind方法,然后将返回值添加到 self._fields[name] 中. 6 即: 7 _fields = { 8 name: wtforms.fields.

Flask核心机制--上下文源码剖析

在App开发中,内嵌WebView始终占有着一席之地.它能以较低的成本实现Android.iOS和Web的复用,也可以冠冕堂皇的突破苹果对热更新的封锁. 然而便利性的同时,WebView的性能体验却备受质疑,导致很多客户端中需要动态更新等页面时不得不采用其他方案. 以发展的眼光来看,功能的动态加载以及三端的融合将会是大趋势. 那么如何克服WebView固有的问题呢? 我们将从性能.内存消耗.体验.安全几个维度,来系统的分析客户端默认WebView的问题,以及对应的优化方案. 性能 对于WebVi

ajax轮询请求实现源码分享

ajax轮询请求状态是ajax学习中非常重要的也是必须掌握的知识点,今天就和大家一起来分享一下这部分内容,一起来看看吧.      这里要实现的功能是:通过扫码微信公众号带参数的二维码,来登录网站.      但很明显,如果ajax不间断的请求服务器,这样会加重服务器的负荷,所以本例采用的是js的setInterval来周期性调用执行一个ajax函数来来向服务器请求数据,但请求成功或者请求一定次数后还未成功时用clearinterval函数清空计时器. 代码和注释如下:(后端采用thinkPHP