Python【day 9】:Python学习(mysql模块、gevent协程、使用yield实现协程操作、通过队列实现协程、通过greenlet实现协程、同步和异步的区别、通过gevent实现单线程下的多socket并发、队列相关、生产者消费者模式)
Python MySQL API
一、查数据 select
#python连接mysql 查询select
#1导入模块
import pymysql #3.5版本
# import MySQLdb #2.7版本
#2建立连接
conn = pymysql.connect(host='192.168.19.130',user='root',passwd='123456',db='p12')#, cursorclass=pymysql.cursors.DictCursor) #3.5版本
# conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb') #2.7版本
#3新建游标实例
cur = conn.cursor()
#4返回符合提交的记录条数
reCount = cur.execute("SELECT * from students")
# print(reCount) #2 这里的2代表一共查出了2条记录
# reCount = cur.execute('insert into UserInfo(Name,Address) values(%(id)s, %(name)s)',{'id':12345,'name':'wupeiqi'})
# conn.commit()
# print(cur.fetchone()) #(1, 'alex', 'man', 18, '151515151') 取出一条放在元组
# print(cur.fetchone()) #(2, 'jack', 'man', 11, '151515251') 在取出一条放在元组
# print(cur.fetchall())
#((1, 'alex', 'man', 18, '151515151'), (2, 'jack', 'man', 11, '151515251'))
#把表中的所有记录全部查询出来,以元组的形式存在大的元组中
# print(cur.fetchmany(2)) #取出前2条记录
#5取出符合条件的字段值 select
for i in cur.fetchall():
# # print(i) #遍历元组,将大元组的子元组打印出来
print(i[0],i[1],i[2],i[3],i[4]) #遍历元组,将子元组的每个字段都打印出来(这里没有返回字段名字)
# print(i[0],i[1]) #遍历元组,将子元组的前2个字段都打印出来(这里没有返回字段名字)
# 1 alex man 18 151515151
# 2 jack man 11 151515251
# for field_desc in cur.description:
# for field_desc in cur:
# print(field_desc)
#6关闭游标
cur.close()
#7 关闭连接
conn.close()
# print(reCount)
显示字段名
#python连接mysql 查询select
#1导入模块
import pymysql #3.5版本
# import MySQLdb #2.7版本
#2建立连接
conn = pymysql.connect(host='192.168.19.130',user='root',passwd='123456',db='p12', cursorclass=pymysql.cursors.DictCursor) #3.5版本
# cursorclass=pymysql.cursors.DictCursor 用于显示字段名
# conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb') #2.7版本
#3新建游标实例
cur = conn.cursor()
#4得到符合条件的条数
reCount = cur.execute("SELECT * from students")
# print(reCount) #2 这里的2代表一共查出了2条记录
# reCount = cur.execute('insert into UserInfo(Name,Address) values(%(id)s, %(name)s)',{'id':12345,'name':'wupeiqi'})
# conn.commit()
# print(cur.fetchone()) #(1, 'alex', 'man', 18, '151515151') 取出一条放在元组
# print(cur.fetchone()) #(2, 'jack', 'man', 11, '151515251') 在取出一条放在元组
# print(cur.fetchall())
#((1, 'alex', 'man', 18, '151515151'), (2, 'jack', 'man', 11, '151515251'))
#把表中的所有记录全部查询出来,以元组的形式存在大的元组中
#5取值 select
for i in cur.fetchall():
# print(i) #遍历元组,将大元组的子元组打印出来
# print(i[0],i[1],i[2],i[3],i[4]) #遍历元组,将子元组的每个字段都打印出来(这里返回字段名字)
print(i["name"],i["sex"]) #遍历元组,将子元组的前2个字段都打印出来(这里根据字段名字查询)
# {'age': 18, 'name': 'alex', 'tel': '151515151', 'id': 1, 'sex': 'man'}
# {'age': 11, 'name': 'jack', 'tel': '151515251', 'id': 2, 'sex': 'man'}
# for field_desc in cur.description:
# # for field_desc in cur:
# print(field_desc[0]) #显示所有字段名
#6关闭游标实例
cur.close()
#7关闭连接
conn.close()
# print(reCount)
二、插入数据
#python连接mysql 增加一条记录insert
#1导入模块
import pymysql #3.5版本
# import MySQLdb #2.7版本
#2建立连接
conn = pymysql.connect(host='192.168.19.130',user='root',passwd='123456',db='p12')#, cursorclass=pymysql.cursors.DictCursor) #3.5版本
# conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb') #2.7版本
#3新建游标实例
cur = conn.cursor()
#4返回新插入的记录条数
reCount = cur.execute('insert into students(name,sex,age,tel) values(%s,%s,%s,%s)',("tom",'male','23','13501145287'))
print(reCount) #1 这里的1代表新插入了1条记录
# reCount = cur.execute('insert into UserInfo(Name,Address) values(%(id)s, %(name)s)',{'id':12345,'name':'wupeiqi'})
#5提交插入操作
conn.commit()
#6插入新纪录后,查询插入后的结果
reCount = cur.execute("SELECT * from students")
# print(cur.fetchone()) #(1, 'alex', 'man', 18, '151515151') 取出一条放在元组
# print(cur.fetchone()) #(2, 'jack', 'man', 11, '151515251') 在取出一条放在元组
# print(cur.fetchall())
#((1, 'alex', 'man', 18, '151515151'), (2, 'jack', 'man', 11, '151515251'))
#把表中的所有记录全部查询出来,以元组的形式存在大的元组中
# print(cur.fetchmany(2)) #取出前2条记录
#7取出符合条件的查询字段值 select
for i in cur.fetchall():
# # print(i) #遍历元组,将大元组的子元组打印出来
print(i[0],i[1],i[2],i[3],i[4]) #遍历元组,将子元组的每个字段都打印出来(这里没有返回字段名字)
# print(i[0],i[1]) #遍历元组,将子元组的前2个字段都打印出来(这里没有返回字段名字)
# 1 alex man 18 151515151
# 2 jack man 11 151515251
# for field_desc in cur.description:
# for field_desc in cur:
# print(field_desc)
#8关闭游标
cur.close()
#9 关闭连接
conn.close()
# print(reCount)
三、删除数据
#python连接mysql 删除一条记录 delete
#1导入模块
import pymysql #3.5版本
# import MySQLdb #2.7版本
#2建立连接
conn = pymysql.connect(host='192.168.19.130',user='root',passwd='123456',db='p12')#, cursorclass=pymysql.cursors.DictCursor) #3.5版本
# conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb') #2.7版本
#3新建游标实例
cur = conn.cursor()
#4返回删除的记录条数
reCount = cur.execute('delete from students where name ="tom"')
print(reCount) #3 这里的1代表新删除了3条记录
# reCount = cur.execute('insert into UserInfo(Name,Address) values(%(id)s, %(name)s)',{'id':12345,'name':'wupeiqi'})
#5提交删除操作
conn.commit()
#6删除纪录后,查询删除后的结果
reCount = cur.execute("SELECT * from students")
# print(cur.fetchone()) #(1, 'alex', 'man', 18, '151515151') 取出一条放在元组
# print(cur.fetchone()) #(2, 'jack', 'man', 11, '151515251') 在取出一条放在元组
# print(cur.fetchall())
#((1, 'alex', 'man', 18, '151515151'), (2, 'jack', 'man', 11, '151515251'))
#把表中的所有记录全部查询出来,以元组的形式存在大的元组中
# print(cur.fetchmany(2)) #取出前2条记录
#7取出符合条件的查询字段值 select
for i in cur.fetchall():
# # print(i) #遍历元组,将大元组的子元组打印出来
print(i[0],i[1],i[2],i[3],i[4]) #遍历元组,将子元组的每个字段都打印出来(这里没有返回字段名字)
# print(i[0],i[1]) #遍历元组,将子元组的前2个字段都打印出来(这里没有返回字段名字)
# 1 alex man 18 151515151
# 2 jack man 11 151515251
# for field_desc in cur.description:
# for field_desc in cur:
# print(field_desc)
#8关闭游标
cur.close()
#9 关闭连接
conn.close()
# print(reCount)
四、修改数据
#python连接mysql 修改记录 update
#1导入模块
import pymysql #3.5版本
# import MySQLdb #2.7版本
#2建立连接
conn = pymysql.connect(host='192.168.19.130',user='root',passwd='123456',db='p12')#, cursorclass=pymysql.cursors.DictCursor) #3.5版本
# conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb') #2.7版本
#3新建游标实例
cur = conn.cursor()
#4返回修改的记录条数
reCount = cur.execute('update students set name = %s WHERE age = "11"' ,('alex',))
#这里“11”后面是逗号不是%,写百分号会报错
print(reCount) #1 这里的1代表新修改了1条记录
# reCount = cur.execute('insert into UserInfo(Name,Address) values(%(id)s, %(name)s)',{'id':12345,'name':'wupeiqi'})
#5提交修改操作
conn.commit()
#6修改纪录后,查询修改后的结果
reCount = cur.execute("SELECT * from students")
# print(cur.fetchone()) #(1, 'alex', 'man', 18, '151515151') 取出一条放在元组
# print(cur.fetchone()) #(2, 'jack', 'man', 11, '151515251') 在取出一条放在元组
# print(cur.fetchall())
#((1, 'alex', 'man', 18, '151515151'), (2, 'jack', 'man', 11, '151515251'))
#把表中的所有记录全部查询出来,以元组的形式存在大的元组中
# print(cur.fetchmany(2)) #取出前2条记录
#7取出符合条件的查询字段值 select
for i in cur.fetchall():
# # print(i) #遍历元组,将大元组的子元组打印出来
print(i[0],i[1],i[2],i[3],i[4]) #遍历元组,将子元组的每个字段都打印出来(这里没有返回字段名字)
# print(i[0],i[1]) #遍历元组,将子元组的前2个字段都打印出来(这里没有返回字段名字)
# 1 alex man 18 151515151
# 2 jack man 11 151515251
# for field_desc in cur.description:
# for field_desc in cur:
# print(field_desc)
#8关闭游标
cur.close()
#9 关闭连接
conn.close()
# print(reCount)
五、批量数据增加
__author__ = 'Administrator'
#-*- coding:utf-8 -*-
#python连接mysql 一次增加多条记录insert
#1导入模块
import pymysql #3.5版本
# import MySQLdb #2.7版本
#2建立连接
conn = pymysql.connect(host='192.168.19.130',user='root',passwd='123456',db='p12')#, cursorclass=pymysql.cursors.DictCursor) #3.5版本
# conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb') #2.7版本
#3新建游标实例
cur = conn.cursor()
#4返回批量新插入的记录条数
li =[
('jack','man',"18","13501145289"),
('tom','male',"19","13501145287"),
]
reCount = cur.executemany('insert into students_innodb(name,sex,age,tel) values(%s,%s,%s,%s)',li)
#单条插入式execute 批量插入是executemany
# reCount = cur.execute('insert into students(name,sex,age,tel) values(%s,%s,%s,%s)',("tom",'male','23','13501145287'))
# print(reCount) #1 这里的1代表新插入了1条记录
# reCount = cur.execute('insert into UserInfo(Name,Address) values(%(id)s, %(name)s)',{'id':12345,'name':'wupeiqi'})
#5提交批量插入操作
conn.commit()
#6插入新纪录后,查询插入后的结果
reCount = cur.execute("SELECT * from students_innodb")
# print(cur.fetchone()) #(1, 'alex', 'man', 18, '151515151') 取出一条放在元组
# print(cur.fetchone()) #(2, 'jack', 'man', 11, '151515251') 在取出一条放在元组
# print(cur.fetchall())
#((1, 'alex', 'man', 18, '151515151'), (2, 'jack', 'man', 11, '151515251'))
#把表中的所有记录全部查询出来,以元组的形式存在大的元组中
# print(cur.fetchmany(2)) #取出前2条记录
#7取出符合条件的查询字段值 select
for i in cur.fetchall():
# # print(i) #遍历元组,将大元组的子元组打印出来
print(i[0],i[1],i[2],i[3],i[4]) #遍历元组,将子元组的每个字段都打印出来(这里没有返回字段名字)
# print(i[0],i[1]) #遍历元组,将子元组的前2个字段都打印出来(这里没有返回字段名字)
# 1 alex man 18 151515151
# 2 jack man 11 151515251
# for field_desc in cur.description:
# for field_desc in cur:
# print(field_desc)
#8关闭游标
cur.close()
#9 关闭连接
conn.close()
# print(reCount)
六、回滚
#python连接mysql 回滚
#1导入模块
import pymysql #3.5版本
# import MySQLdb #2.7版本
#2建立连接
conn = pymysql.connect(host='192.168.19.130',user='root',passwd='123456',db='p12')#, cursorclass=pymysql.cursors.DictCursor) #3.5版本
# conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb') #2.7版本
#3新建游标实例
cur = conn.cursor()
#4返回批量新插入的记录条数
li =[
('jack1','man',"18","13501145289"),
('tom1','male',"19","13501145287"),
]
reCount = cur.executemany('insert into students_innodb(name,sex,age,tel) values(%s,%s,%s,%s)',li)
#单条插入式execute 批量插入是executemany
# reCount = cur.execute('insert into students(name,sex,age,tel) values(%s,%s,%s,%s)',("tom",'male','23','13501145287'))
# print(reCount) #1 这里的1代表新插入了1条记录
# reCount = cur.execute('insert into UserInfo(Name,Address) values(%(id)s, %(name)s)',{'id':12345,'name':'wupeiqi'})
#5 没有提交前,可以回滚插入操作;如果已经提交了,就无法回滚了,注意默认数据库引擎需要修改成InnoDB
conn.rollback()
#mysql 默认的数据库引擎是MyISAM,不支持事务和外键,也可使用支持事务和外键的InnoDB。修改数据库的默认引擎即可
#5提交批量插入操作
# conn.commit()
#6插入新纪录后,查询插入后的结果
reCount = cur.execute("SELECT * from students_innodb")
# print(cur.fetchone()) #(1, 'alex', 'man', 18, '151515151') 取出一条放在元组
# print(cur.fetchone()) #(2, 'jack', 'man', 11, '151515251') 在取出一条放在元组
# print(cur.fetchall())
#((1, 'alex', 'man', 18, '151515151'), (2, 'jack', 'man', 11, '151515251'))
#把表中的所有记录全部查询出来,以元组的形式存在大的元组中
# print(cur.fetchmany(2)) #取出前2条记录
#7取出符合条件的查询字段值 select
for i in cur.fetchall():
# # # print(i) #遍历元组,将大元组的子元组打印出来
print(i[0],i[1],i[2],i[3],i[4]) #遍历元组,将子元组的每个字段都打印出来(这里没有返回字段名字)
# print(i[0],i[1]) #遍历元组,将子元组的前2个字段都打印出来(这里没有返回字段名字)
# 1 alex man 18 151515151
# 2 jack man 11 151515251
# for field_desc in cur.description:
# for field_desc in cur:
# print(field_desc)
#8关闭游标
cur.close()
#9 关闭连接
conn.close()
# print(reCount)
gevent协程
# 使用yield实现协程操作例子(生产者每次做2个包子,一共做2次包子,2次一共做了4包子,
# 分别给2个消费者吃。每个消费者一次吃一个包子,一共吃2次)
import time
import queue
def consumer(name):
pass
print("start eat baozi")
while True:
new_baozi = yield #这里yield接收22行的send过来的包子标号
print("[%s] is eating baozi %s" % (name,new_baozi))
def producer(name):
pass
r = c1.__next__() #生成器 迭代器 3.5 next加上下划线
r = c2.__next__()
n= 0 #n代表包子的编号
while n<2:
n+=1
print("[producer [%s] is making baozi %s]" %(name, n)) #应该是生产者先做包子,消费者再吃,先打印做包子,在打印吃包子
c1.send(n) #发送到12行的 yield
c2.send(n)
# print("[producer is making baozi %s]" % n)
if __name__ == "__main__":
c1 = consumer("c1") #2个消费者实例
c2 = consumer("c2")
p1 = producer("p1") #1个生产者实例(生产者每次做2个包子,给2个消费者吃)
# p2 = producer("p2")
二#通过队列实现协程
import time
import queue
import threading
q = queue.Queue() #创建队列实例
def consumer(n):
while True: #消费者循环接受任务(吃包子)
print("\033[32;1mconsumer [%s]\033[0m get task: %s" % (n,q.get()))
#从队列取出任务 get
time.sleep(1)
q.task_done() #消费者每次接收完任务(吃完包子)就通知队列
def producer(n):
count =1
while True: #生产者循环产生新的任务(做包子)
print("producer [%s] produced a new task: %s" % (n,count))
q.put(count) #将任务放进队列
count +=1 #任务标号自增1
q.join() #等所有的消费者都吃完包子了,队列就会通知生产者重新做包子
# (而不是,一个消费者吃完了,缺一个包子,就做一个包子)
print("all task has been consumed by consumers")
c1 = threading.Thread(target=consumer,args=[1,])
c2 = threading.Thread(target=consumer,args=[2,])
# c3 = threading.Thread(target=consumer,args=[3,])
p1 = threading.Thread(target=producer,args=["jack",])
p2 = threading.Thread(target=producer,args=["tom",])
c1.start()
c2.start()
# c3.start()
p1.start()
p2.start()
#问题:3个消费者 1000个生产者,会出现3个包子吃完后,1000个生产者又生产了1000个包子
三#通过greenlet实现协程
from greenlet import greenlet
def test1():
print(12) #1
gr2.switch()
print(34) #3
gr2.switch()
def test2():
print(56) #2
gr1.switch()
print(78) #4
gr1 = greenlet(test1) #新建实例
gr2 = greenlet(test2)
gr1.switch() #设定切换的起始位置
四#通过gevent实现协程
#协程是遇到阻塞,就切换到别的协程
import gevent
def foo():
pass
print("running in foo") #1
gevent.sleep(1) #协程是遇到阻塞(IO或者睡眠),就切换到别的协程
print("Explict context swith to foo again") #3
def bar():
pass
print("Explict context to bar") #2
gevent.sleep(3)
print("Implicit context switch back to bar") #4
gevent.joinall(
[gevent.spawn(foo),
gevent.spawn(bar)]
)
五#同步和异步的区别
#协程是遇到阻塞,就切换到别的协程
import gevent
def task(pid):
"""
Some non-deterministic task
"""
gevent.sleep(0.5)
print('Task %s done' % pid)
def synchronous(): #同步
for i in range(1,10):
task(i)
def asynchronous(): #异步
threads = [gevent.spawn(task, i) for i in range(10)]
gevent.joinall(threads)
print('Synchronous:') #同步
synchronous()
print('Asynchronous:') #异步
asynchronous()
六#协程是遇到阻塞(IO或者睡眠),就切换到别的协程
from gevent import monkey;monkey.patch_all()
import gevent
from urllib.request import urlopen
def f(url):
pass
print("get:%s" % url)
res = urlopen(url)
# print(res) #<http.client.HTTPResponse object at 0x0000000002F51E80>
data = res.read()
# print(data)
print("%s bytes received from %s"%(len(data),url))
gevent.joinall([
gevent.spawn(f,"https://www.python.org/"),
gevent.spawn(f,"https://www.yahoo.com/"),
gevent.spawn(f,"https://github.com/")
])
__author__ = 'Administrator'
#-*- coding:utf-8 -*-
七# 通过gevent实现单线程下的多socket并发
服务端:
import sys
import socket
import time
import gevent
from gevent import socket,monkey
monkey.patch_all() #设置不阻塞
def server(port):
s = socket.socket()
s.bind(("0.0.0.0",port)) #这里2个小括号
s.listen(500)
while True:
cli,addr = s.accept()
gevent.spawn(handle_request,cli)
def handle_request(s):
try:
while True:
data = s.recv(1024) #接受客户端消息
print("recv:",str(data,"utf8"))
s.send(data) #把客户端发送的消息返回给客户端
if not data:
s.shutdown(socket.SHUT_WR)
except Exception as ex:
print(ex)
finally:
s.close()
if __name__ == '__main__':
server(8001)
客户端
import socket
host = "localhost"
port = 8001
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((host,port))
while True: #客户端循环输入消息
pass
msg = bytes(input(">>:"),"utf8")
s.sendall(msg)
data = s.recv(1024)
print("received",str(data,"utf8"))
s.close()
队列相关
#1先入先出
import queue
q=queue.Queue(3) #10是队列长度 先入先出
q.put([1,2,3]) #这里队列可以存放的数据类型:列表 字典 字符串 实例
q.put([12,2,3])
q.put([12,2,3]) #queue.Full
# 第二个参数超时是2秒,就是队列满了的时候,不会无限制等,2秒后就返回queue.Full
print(q.qsize()) #2 队列长度
print(q.get())
print(q.get())
print(q.get())
# print(q.get(timeout=2)) #queue.Empty
# 第二个参数超时是2秒,就是队列空的时候,不会无限制等,2秒后就返回queue.Empty
print(q.qsize()) #0 队列
# [1, 2, 3]
# [12, 2, 3]
#2后入先出
import queue
q=queue.LifoQueue(10) #10是队列长度 后入先出
q.put([1,2,3])
q.put([12,2,3])
print(q.get())
print(q.get())
# [12, 2, 3]
# [1, 2, 3]
#3队列设定优先级
import queue
q=queue.PriorityQueue(10) #10是队列长度
q.put((1,3)) #第一个参数是优先级,第二个参数是值,优先级越小,优先级别越高
q.put((3,5))
q.put((2,6))
print(q.get())
print(q.get())
print(q.get())
# (1, 3)
# (2, 6)
# (3, 5)
4#队列-生产者消费者模式
import time,random
import queue,threading
q = queue.Queue()
def producer(name):
count = 0
while count <20:
time.sleep(random.randrange(3)) #控制生产包子的速度
q.put(count) #生产者把包子放入队列
print("producer [%s] has produced [%s] baozi" % (name,count))
count +=1
def consumer(name):
pass
count = 0
while count <20:
time.sleep(random.randrange(4)) #控制消费包子的速度
if not q.empty(): #如果队列不是空的
data = q.get() #消费者从队列取包子
print(data)
print("\033[32;1mconsumer [%s] has eat [%s] baozi...\033[0m" % (name,data))
else:
print("no baozi anymore") #如果生产的速度慢于消费的速度,就会提示包子不够
count +=1
p1 = threading.Thread(target=producer,args=("a",)) #创建一个生产者实例-线程 可以多个生产者
c1 = threading.Thread(target=consumer,args=("b",)) #创建一个消费者实例-线程 也可以多个消费者
p1.start() #启动线程
c1.start() #启动消费者线程

浙公网安备 33010602011771号