面试
-------------------------------------------------
# 脏读,不可重复读,幻读 ,mysql5.7以后默认隔离级别是什么?
-脏读:指的是读到了其他事务未提交的数据,未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中,也就是不存在的数据。读到了并一定最终存在的数据,这就是脏读
-不可重复读:指的是在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据出现不一致的情况
-幻读:并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读
-https://www.cnblogs.com/liuqingzheng/p/16480047.html
--------------------------------------------------
# 什么是qps,tps,并发量,pv,uv
-qps:Queries Per Second,每秒查询率,一台服务器每秒能够响应的查询次数
-tps:Transactions Per Second,是每秒处理的事务数,包括一条消息入和一条消息出,加上一次用户数据库访问
-并发量:系统同时处理的请求数量
-PV(Page View):页面访问量,即页面浏览量或点击量,用户每次刷新即被计算一次。可以统计服务一天的访问日志得到
-UV(Unique Visitor):独立访客,统计1天内访问某站点的用户数。可以统计服务一天的访问日志并根据用户的唯一标识去重得到
-DAU(日活)DAU(Daily Active User),日活跃用户数量。常用于反映网站、app、网游的运营情况。DAU通常统计一日(统计日)之内,登录或使用了某个产品的用户数(去除重复登录的用户),与UV概念相似
-MAU(Month Active User):月活跃用户数量,指网站、app等去重后的月活跃用户数量
# 什么是接口幂等性问题,如何解决?
-幂等:幂等(idempotent、idempotence)是一个数学与计算机学概念
-一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同
-接口幂等性:无论调用多少次,产生的效果是一样的
-get 获取数据天然幂等
-put 修改数据天然幂等
-delete 删除 天然幂等
-post 新增数据,会出现不幂等的情况,要把它做成幂等性的
-解决:
1 唯一主键 unique 新增用户用用户名唯一,但是订单问题解决不了
2 token机制,随机字符串
-在使用新增之前,先生成一个随机字符串token,保存起来,只要调用新增接口,就必须携带随机字符串token,到后端,校验这个token在不在我们保存的里面,如果在,说明正常,删除token,允许新增,如果不在就不允许新增
3 前端:按钮只能点击一次
.
.
.
.
昨日回顾
# 1 cbv 使用
-写一个类继承MethodView,写get,post。。。
-类属性decorators = [auth,]可以加装饰器
# 2 cbv执行流程
-1 跟djagno流程一样
-2 entpoint 作用路径别名,add_url_rule(view_func=IndexView.as_view('index'))
-3 为什么entpoint不传,是被路由装饰器装饰的函数名: 函数.__name__
-4 装饰器的执行先后顺序
# 3 模板语法
# 4 请求响应
-请求:全局request对象,在不同视图函数中尽管使用,不会错乱
-method
-path
-files
-form
-argvs。。。。
-响应:四件套
-响应对象,make_response包裹一下四件套之一
-set_cookies
-响应对象.headers 响应头
# 5 session使用
-设置秘钥
-全局导入,直接赋值,取值
# 6 session执行流程
-open_session:前端写到cookie到后端,后端取出cookie对应的value值,解密,转到session对象中,后续再视图函数中,使用session即可
-save_session:请求走的时候,校验session有没有被改过,如果被改了,删除cookie,重新设置cookie
-session用起来像字典---》如何做,一个对象可以像字典一样使用, __getitem__ __setitem__,只要调用__setitem__ 就说明动了,对象属性 modify,一开始false,只要触发了__setitem__,置为true,后期只要判断modify,就可以判断session有没有被改过
# 7 闪现:跨请求获取到之前请求存放的数据,取一次就没了 关注django的message框架
-flash('%s,我错了'%name)
-get_flashed_messages()
# 8 请求扩展
-before_request
-after_request
-before_first_request
-teardown_request:错误日志记录
-errorhandler:是某种状态码,就会执行它
今日内容
1 蓝图的使用
# blueprint 翻译过来的,称之为蓝图
# 作用是:之前全在一个py中写flask项目,后期肯定要划分目录
# 不用蓝图,划分目录
no_blueprint_flask # 项目名
src #核心源码位置
__init__.py # 包 里面实例化得到了app对象,
models.py #放表模型
views.py # 放视图函数
static # 放静态资源
templates # 放模板
home.html # 模板
manage.py # 启动文件
# 蓝图的使用步骤
-第一步:导入蓝图类 from flask import Blueprint
-第二步:实例化得到蓝图对象 us=Blueprint('user',__name__)
-第三步:在app中注册蓝图 app.register_blueprint(us)
-第四步:在不同的views.py 使用蓝图注册路由 @us.route('/login')
-补充:蓝图可以有自己的静态文件和模板
-补充:注册蓝图时,可以使用前缀,必须以/ 开头
# 使用蓝图,划分小型项目目录
little_blueprint # 项目名
-src # 核心代码
-static # 静态文件
-1.jpg # 图片
-templates # 模板文件
-user.html # 模板
-views # 视图函数存放位置
-order.py # 订单相关视图
-user.py # 用户相关视图
-__init__.py # 包
-models.py # 表模型
-manage.py # 启动文件
# 使用蓝图,划分大型项目目录 多个app,像django一样
big_blueprint # 项目名
-src # 核心文件
-admin # admin的app
-static # 静态文件
-1.jpg # 图片
-templates # 模板文件目录
-admin_home.html # 模板文件
-__init__.py # 包
-models.py # 表模型
-views.py # 视图函数
-home # home app
-order # orderapp
-__init__.py # 包
-settings.py # 配置文件
-manage.py # 启动文件
2 g对象
# g 对象 是什么?
-global的缩写,再python中是个关键字,不能以关键字作为变量名,干脆用了g
-g 对象,在整个请求的全局,可以放值,可以取值
-全局变量,在任意位置导入使用即可
-它为什么不学django使用request作为上下文?
-因为使用request,可能会造成request数据的污染,不小心改了request的属性,但你不知道
-建议使用g 是空的,放入之后在当次请求中全局优先
# 以后想在当次请求中,放入一些数据,后面使用,就可以使用g对象
# g和session有什么区别?
-g 是只针对于当次请求
-session针对于多次请求
from flask import Flask, g, request
app = Flask(__name__)
app.debug = True
@app.before_request
def before():
if 'home' in request.path:
g.xx = 'xx'
def add(a, b):
# print('---',g.name)
print('---', request.name)
return a + b
@app.route('/')
def index():
print(g.xx)
name = request.args.get('name')
# g.name = name
request.method = name
res = add(1, 2)
print(res)
return 'index'
@app.route('/home')
def home():
print(g.xx)
return 'index'
if __name__ == '__main__':
app.run()
3 数据库连接池
# flask 操作mysql
-使用pymysql
-在视图函数中,创建pymysql的连接,查数据,查完,返回给前端
-有什么问题? 来一个请求,创建一个连接,请求结束,连接关闭 (djanog就是这么做的)
-把连接对象,做成全局的,在视图函数中,使用全局的连接,查询,返回给前端
-有什么问题?会出现数据错乱,详见下图
# 解决上面的两个问题
-数据库连接池
-创建一个全局的池
-每次进入视图函数,从池中取一个连接使用,使用完放回到池中,只要控制池的大小,就能控制mysql连接数
# 使用第三方数据库连接池,使用步骤
-1 安装 pip install dbutils
-2 使用:实例化得到一个池对象
-3 在视图函数中导入使用
conn = pool.connection()
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute('select id,title,author_img from aritcle limit 2')
res = cursor.fetchall()
# 带池的代码
@app.route('/article_pool')
def article_pool():
conn = pool.connection()
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute('select id,title,author_img from aritcle limit 2')
res = cursor.fetchall()
print(res)
return jsonify(res)
# 不带池的代码
@app.route('/article')
def article():
conn = pymysql.connect(user='root',
password="",
host='127.0.0.1',
database='cnblogs',
port=3306)
cursor = conn.cursor(pymysql.cursors.DictCursor)
time.sleep(random.randint(1,3))
cursor.execute('select id,title,author_img from aritcle limit 2')
res = cursor.fetchall()
cursor.close()
conn.close()
return jsonify(res)
# 压力测试代码
from threading import Thread
import requests
def task():
res = requests.get('http://127.0.0.1:5000/article_pool')
print(len(res.text))
if __name__ == '__main__':
for i in range(500):
t = Thread(target=task)
t.start()
## 效果是:
使用池的连接数明显小
不使用池连接数明显很大
# 查看数据库连接数
show status like 'Threads%'
作业
# 面试题
1 什么是gil锁,有什么作用
2 python的垃圾回收机制是什么样的
3 解释为什么计算密集型用多进程,io密集型用多线程
# 把今天讲得代码写一遍