导包:会出来个_pycache_,里面放缓存,第一次运行程序跑的慢,第二次产生缓存之后执行代码速度会变快。缓存全是二进制文件(又叫字节码文件)
测试
web程序开发过程一般包括下面几个阶段:[需求分析、设计分析、实现阶段、测试阶段]
测试的分类:
- 单元测试:对单独的代码块 ( 例如函数 ) 分别进行测试,以保证它们的正确性(由程序员完成)
- 集成测试:对大量的程序单元协同工作情况做测试
- 系统测试:同时对整个系统的正确性进行检查,而不是针对独立的片段
单元测试:经常使用的是断言 ( assert )
断言:和生活中到的语言,断定是一样的
格式:assert boolean表达式 , 异常信息
例:如果num1是整数,测试通过,否则返回异常信息,显示"num1必须是整数类型"assert isinstance(num1 , int) , "num1必须是整数类型"
isinstance:判断类型
格式:isinstance( 变量 , 数据类型)
如果变量是该数据类型,返回True,否则返回False
def divsion(num1,num2):
assert isinstance(num1,int),"num1必须是整数类型"
return num1/num2
print(divsion(10,5))
print(divsion("10",5))
搜索:
- 1.搜当前文件 ctrl + f
- 2.搜索整个项目 ctrl + shift + f
- 3.搜索指定文件目录 ctrl + shift + f 找到scope的directory
测试:
- 1.导入类unittest 的TestCase
from unittest import TestCase - 2.编写自定义测试类,继承TestCase
class DataBaseTest(TestCase): - 3.编写两个固定方法:setUp()和tearDown()
setUp()测试执行前执行,tearDown()出错的时候执行
测试类可以直接运行(不用写__name__入口),右键,光标放到哪个测试业务方法右键运行,执行哪个测试方法
测试业务方法必须以test开头
千万不能在同一个数据库里做测试,必须要新建
案例:测试昨天的图书馆数据库
from unittest import TestCase
from demo02library import *
# 定义类,继承自TestCase
class DataBaseTest(TestCase):
def setUp(self):
# print("setUp")
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/library16_test'
db.create_all()
def test_database_add_data(self):
# 1.创建作者对象,添加到数据库中
author = Author(name="banzhang")
db.session.add(author)
db.session.commit()
# 2.查询出来
author2 = Author.query.filter(Author.name=="banzhang").first()
# 延时方法:
import time
time.sleep(10)
# 3.断言了,作者对象一定不能为空,并且名字一定是班长
self.assertIsNotNone(author2,"author2一定不能为空")
self.assertEqual(author2.name,"name的值一定是班长")
def tearDown(self):
print("tearDown")
assertIsNotNone格式:必须写在测试类的方法里,不然找不到
from unittest import TestCase
class 类名(TestCase):
def test后缀(self):
self.assertIsNotNone(变量,"字符串")
assertIsNotNone:变量存在,则pass,不存在,测试时显示字符串
类似的还有很多,进去查看
Redis
Redis:非关系型数据库的一种
nosql介绍:一类新数据的数据库(not only sql)
泛指非关系型数据库
不支持sql语法
存储跟传统的完全不同,都是KV(keyvalue)形式,每种都有自己的api和语法,以及擅长的业务场景
nosql产品种类:MongoDB、Redis
NoSQL和SQL比较:
sql适用关系特别复杂的数据查询场景,nosql反之
sql支持事务,nosql不支持事务
虚读(幻读):看一个栏目,展开下滑到一半,去看另一个栏目,然后切回第一个栏目还能回到刚刚停留的位置
Redis简介:c语言编写,NoSQL阵营一员
Redis特效:数据存在内存(速度贼快),电脑关机时拍快照放硬盘,重启再次加载恢复;支持列表、集合、哈希等结构的存储,支持master-slave(哨兵模式)的集群
Redis安装和配置:另起文章说明
redis的logo:面包片
终端下:
查看帮助:redis-server --help
查看redis服务器进程:ps-aux|grep redis
杀死进程:kill -9 进程PIDsudo redis-server /etc/redis/redis.conf 加载指定的配置文件
启动服务端:redis-server
另开一个终端,进入客户端:redis-cli
查看redis服务器进程:ps-aux
客户端下:
运行测试,看是否能联通:ping
收到个PONG,表示连接OK
redis使用的数据库(类似mysql的use database)可以配置,默认是有16个,编号0-15,默认使用数据库0
切换到数据库10:select 10 返回个ok表示成功
增删改查:
string类型:
设置:set ; 获取:getset name zhangsan 设置name为zhangsanget name 获取name
设置存在一定的时间:setexsetex age 10 13 设置age为13,只存在10s
设置多个key和value:msetmset name zhangsan sex man height 180get sex
字符串追加:appendset name zhangsanappend name feng 给name追加个fengget name 结果是zhangsanfengappend haha 20 要是key没有,则自动生成
获取多个:mgetmget name sex height haha
查看:keyskeys * 查看全部keys h* 查看h开头keys *x 查看x结尾keys *e* 查看包含e的
查看是否存在:existsexists name 查看name是否存在,存在返回1,不存在返回0
查看类型:typetype name 查看name的类型
删除:deldel height haha 删掉height和haha,返回的是影响的结果数
删除所有:flushallflushall 刷新所有,所有内容都清空
设置expireexpire name 10 给name设置10秒有效期ttl name 查看name还有几秒到期,为负数就到期了
哈希类型:
redis操作hash类型
格式:hset key field value
filed:域的意思
看朋友圈滚滚滚,切出去,再切回来还能继续看
使用场景:分页缓存。跟哈希有关(类似字典、但又不一样。哈希key=>字典变量名,哈希field=>字典key)
hset person age 13hset person name laowangkeys * 结果显示person只有一个get person 报错,要用hget过去,而且hget person 也报错,后面要加filedhget person namehmset person name laowang age 18 sex man height 180 设置多个fieldhmget person name age sex height 获取多个fieldhkeys person 查看person里有多少个fieldhdel person name height 删除person的name和height域
list类型:类似双端队列?
左侧插入数据,格式:lpush key value1 value2 ....lpush list 1 2 3 4
右侧插入数据:rpush ...
左侧查询数据:lrange(没有rrange)lrange list 0 3 结果为 4,3,2,1,0和3是索引
linsert list before 3 30 在3前面插入个30
linsert list after 3 300 在3后面加入个300
lrange list 0 -1 获取从后到前
lset list 2 3000 将2改为3000
删除:lrem key count value 将key域列表中,count次,值为value的删掉
count:0表示所有,正数是从头开始,负数是从尾开始,删|count|个lrem list 2 c 从头开始,删两个clrem list -3 a 从尾开始,删三个c
set类型:无序集合
set:无序,不重复sadd myset 1 2 3 7 5 8 1 2 3 设置集合,添加数据
sadd myset zhangsan lisi wangwu
smembers myset 结果:
sadd myset 1 myset添加1srem myset 7 删除myset的7
删除集合用deldel myset
zset:有序类型
权重:zaddzadd myzset 10 zhangsan 20 lisi 30 wangwu 10:zhangsan,20:lisi,30:wangwu
zrange myzset 0 -1 查看权重
zrangebyscore myzset 19 21 查看在19~21之间的
zscore myzset wangwu 推导wangwu的权重
zrem myzset zhangsan 删掉zhangsan
zrange myzset 0 -1
redis在python中使用
3个步骤:
- 1.导入redis类
- 2.创建redis对象
- 3.调用方法
例:
# 1.导入redis类
import redis
# 2.创建redis对象,decode_response=True,默认就会解码
# 形参是默认的,可以都不写,decode_response是解码,不然读出来是字节码形式
redis_store = redis.StrictRedis(host="127.0.0.1",port=6379,decode_response=True)
# 3.调用方法
# 存储数据
redis_sotre.set("name","laowang")
# 获取数据
value = redis_store.get("name")
print(value)
# 修改数据
redis_store.set("name","banzhang")
value = redis_store.get("name")
print(value)
# 删除数据
redis_store.delete("name")
value = redis_store.get("name")
print(value)
redis.StrictRedis()按 ctrl + p查看参数,如果不写响应解码 decode_response=True,则数据以字节码形式显示'b'laowang
集群
主从概念:一个master可以有多个slave,一个slave可以有多个slave,如此下去就是集群
主从搭建:
pass,晚点专门写另一篇文章
配置主从:
- 1.
ifconfig查看ip - 2.修改/etc/redis/redis.conf
- 3.将127.0.0.1改成ip(bind的那行)
- 4.如果继承搭建不了,将protected-mode改为no
配置文件目录为/usr/local/redis/redis.conf(Ubuntu16是这个,18和其它的系统我就不知道了)sudo cp /usr/local/redis/redis.conf /etc/redis/
将redis.conf拷贝个,目标文件slaveof.conf(同目录,放到另一台服务器,如果没有改下端口也行)
配置slaveof,主人是谁: slave 主人ip 主人端口
启动起来,可指定配置文件:sudo redis-server redis.confsudo redis-server slaveof.conf
查看是否有主从:redis-cli -h ip info Relication
然后主从分离。主人负责在redis写,奴隶负责读redis-cli -h ip -p 端口
奴隶和主人都启动
主人即可写,也可以读(基本不用);奴隶只能做读
如果同时的访问量过大(1000w),主服务器肯定就会挂掉,大公司都会有很多的服务器(华东地区、华南、港澳台)
当请求来时,先由负载均衡服务器处理,把请求转发到另外的一台服务器上
负载均衡服务器:Negix
分类:
软件层面(一台电脑,靠软件启动多个redis服务),不能应付高并发
硬件层间(多台电脑,每个都启动一个或多个redis服务),可以应付高并发
集群搭建:
在conf搞下面代码port 端口号bind ip地址daemonize yes // 守护进程,是否运行后台进程pidfile ??.pidcluster -enabled yes // 是否允许创建集群cluster -config -file //配置文件cluster -node -timeout 15000 //超时appendonly yes // 是否允许其他加入进来
必须三个以上,才能成为集群,不然搭建不起来
配置好6个conf后,启动服务,然后搞rbredis-trib.rb
然后创建集群:一旦创建好后,主从就会给你分配好了,会提示你要不要接受这种配置
会跳出来个有个slots,槽的意思,一个是0~16383,它计算你要搞的内容在哪个槽里面,你的在哪个槽,它就给你弄到对于的服务器
槽的算法:CRC16算法
跟python交互
from rediscluster import *
if __name__ == '__main__':
try:
# 构建所有的节点,Redis会使⽤CRC16算法,将键和值写到某个节点上
startup_nodes = [
{'host': '192.168.26.128', 'port': '7000'},
{'host': '192.168.26.130', 'port': '7003'},
{'host': '192.168.26.128', 'port': '7001'},
]
# 构建StrictRedisCluster对象
src=StrictRedisCluster(startup_nodes=startup_nodes,decode_responses=True)
# 设置键为name、值为itheima的数据
result=src.set('name','itheima')
print(result)
# 获取键为name
name = src.get('name')
print(name)
except Exception as e:
print(e)