python 闯关之路四(下)(并发编程与数据库编程)
并发编程重点:
- 并发编程:线程、进程、队列、IO多路模型
- 操作系统工作原理介绍、线程、进程演化史、特点、区别、互斥锁、信号、
- 事件、join、GIL、进程间通信、管道、队列。
- 生产者消息者模型、异步模型、IO多路复用模型、select\poll\epoll 高性
- 能IO模型源码实例解析、高并发FTP server开发
1、请写一个包含10个线程的程序,主线程必须等待每一个子线程执行完成之后才结束执行,每一个子线程执行的时候都需要打印当前线程名、当前活跃线程数量;
- from threading import Thread,currentThread,activeCount
- import time
- def task(n):
- print('线程名:%s----%s'%(currentThread().name,n))
- time.sleep(1)
- print('数量:%s'%activeCount())
- if __name__ == "__main__":
- t_li = []
- for i in range(10):
- t = Thread(target=task,args=(i,))
- t.start()
- t_li.append(t)
- for t in t_li:
- t.join()
- print('主,end----')
2、请写一个包含10个线程的程序,并给每一个子线程都创建名为”name”的线程私有变量,变量值为“james”;
- from threading import Thread
- def task(name):
- print('%s is running'%name)
- print('end ---')
- if __name__ == "__main__":
- for i in range(10):
- t = Thread(target=task,args=('james_%s'%i,))
- t.start()
- print('主 end ---')
3、请使用协程写一个消费者生产者模型;
- def consumer():
- while True:
- x = yield
- print('消费:', x)
- def producter():
- c = consumer()
- next(c)
- for i in range(10):
- print('生产:', i)
- c.send(i)
- producter()
4、写一个程序,包含十个线程,子线程必须等待主线程sleep 10秒钟之后才执行,并打印当前时间;
- from threading import Thread,Event
- import time
- import datetime
- def task():
- # while not event.is_set():
- # print('...')
- print('...')
- event.wait(10)
- print('time:',datetime.datetime.now())
- if __name__ == '__main__':
- event = Event()
- for i in range(10):
- t = Thread(target=task)
- t.start()
- time.sleep(10)
- event.set()
5、写一个程序,包含十个线程,同时只能有五个子线程并行执行;
- from threading import Thread,Semaphore,currentThread
- import time
- def task(n):
- sm.acquire()
- print('%s---'%n,currentThread().name)
- time.sleep(1)
- print('end----')
- sm.release()
- if __name__ == '__main__':
- sm = Semaphore(5)
- for i in range(10):
- t = Thread(target=task,args=(i,))
- t.start()
6、写一个程序 ,包含一个名为hello的函数,函数的功能是打印字符串“Hello, World!”,该函数必须在程序执行30秒之后才开始执行(不能使用time.sleep());
- from threading import Timer
- def hello(name):
- print('%s say '%name,'Hello World!')
- if __name__ == "__main__":
- t = Timer(5,hello,args=('james',))
- t.start()
7、写一个程序,利用queue实现进程间通信;
- from multiprocessing import Process,Queue,current_process
- import time
- def consumer(q):
- while True:
- res = q.get()
- if not res:break
- print('消费了:',res,'--',current_process().name)
- def producter(q):
- for i in range(5):
- print('生产:',i)
- time.sleep(1)
- q.put(i)
- if __name__ == "__main__":
- q = Queue()
- p1 = Process(target=producter,args=(q,))
- c1 = Process(target=consumer,args=(q,))
- c2 = Process(target=consumer,args=(q,))
- p1.start()
- c1.start()
- c2.start()
- p1.join()
- q.put(None)
- q.put(None)
- print('主')
- # JoinableQueue
- from multiprocessing import Process,JoinableQueue,current_process
- import time
- def consumer(q):
- while True:
- res = q.get()
- print('消费了:',res,'--',current_process().name)
- q.task_done()
- def producter(q):
- for i in range(5):
- print('生产:',i,'--',current_process().name)
- time.sleep(1)
- q.put(i)
- q.join()
- if __name__ == "__main__":
- q = JoinableQueue()
- p1 = Process(target=producter,args=(q,))
- p2 = Process(target=producter, args=(q,))
- c1 = Process(target=consumer,args=(q,))
- c2 = Process(target=consumer,args=(q,))
- p1.start()
- p2.start()
- c1.daemon = True
- c2.daemon = True
- c1.start()
- c2.start()
- p1.join()
- p2.join()
- print('主')
8、写一个程序,利用pipe实现进程间通信;
- from multiprocessing import Process,Pipe
- def task(conn):
- conn.send('hello world')
- conn.close()
- if __name__ == "__main__":
- parent_conn,child_conn = Pipe()
- p = Process(target=task,args=(child_conn,))
- p.start()
- p.join()
- print(parent_conn.recv())
9、使用selectors模块创建一个处理客户端消息的服务器程序;
- # server blocking IO
- import socket
- server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
- server.bind(('127.0.0.1',8080))
- server.listen(5)
- while True:
- conn,addr = server.accept()
- print(addr)
- while True:
- try:
- data = conn.recv(1024)
- if not data: break
- conn.send(data.upper())
- except Exception as e:
- print(e)
- break
- # server IO多路复用 selectors 会根据操作系统选择select poll epoll
- import socket
- import selectors
- sel = selectors.DefaultSelector()
- def accept(server_fileobj,mask):
- conn,addr = server_fileobj.accept()
- print(addr)
- sel.register(conn,selectors.EVENT_READ,read)
- def read(conn,mask):
- try:
- data = conn.recv(1024)
- if not data:
- print('closing..',conn)
- sel.unregister(conn)
- conn.close()
- return
- conn.send(data.upper())
- except Exception:
- print('closeing...',conn)
- sel.unregister(conn)
- conn.close()
- server_fileobj = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
- server_fileobj.bind(('127.0.0.1',8080))
- server_fileobj.listen(5)
- server_fileobj.setblocking(False)
- sel.register(server_fileobj,selectors.EVENT_READ,accept)
- while True:
- events = sel.select()
- for sel_obj,mask in events:
- callback = sel_obj.data
- callback(sel_obj.fileobj,mask)
- # client
- # -*- coding:utf-8 -*-
- import socket
- client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
- client.connect(('127.0.0.1',8080))
- while True:
- msg = input('>>>:').strip()
- if not msg:continue
- client.send(msg.encode('utf-8'))
- data = client.recv(1024)
- print(data.decode('utf-8'))
10、使用socketserver创建服务器程序时,如果使用fork或者线程服务器,一个潜在的问题是,恶意的程序可能会发送大量的请求导致服务器崩溃,请写一个程序,避免此类问题;
- # server socketserver 模块内部使用IO多路复用 和多进程/多线程
- import socketserver
- class Handler(socketserver.BaseRequestHandler):
- def handle(self):
- print('new connection:',self.client_address)
- while True:
- try:
- data = self.request.recv(1024)
- if not data:break
- print('client data:',data.decode())
- self.request.send(data.upper())
- except Exception as e:
- print(e)
- break
- if __name__ == "__main__":
- server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),Handler)
- server.serve_forever()
11、请使用asyncio实现一个socket服务器端程序;
数据库重点:
- 1、数据库介绍、类型、特性
- 2、MySQL数据库安装、连接、启动、停止
- 3、表字段类型介绍、主键约束、表创建语句
- 4、常用增删改查语句、分组、聚合
- 5、外键管理、unique字段、表结构修改语法
- 6、跨表查询,inner join、left join、right join、full join语法
- 7、复杂SQL语句如group by、子查询、函数的使用
- 8、索引原理及作用、普通索引、多列索引、唯一索引、全文索引等
- 9、基于hash&b+树索引的实现原理,索引的优缺点剖析
- 10、事务原理,ACID特性,应用场景讲解
- 11、事务回滚
- 12、触发器的特性,应用场景
- 13、触发器的增删改查方法
- 14、存储过程的作用及应用场景
- 15、创建存储过程,参数传递,流程控制语句if\while\repeat\loop等,动态SQL的创建
- 16、视图的作用及使用场景,视图的增删改查
- 17、数据库权限管理,用户管理
- 18、数据库备份命令及工具讲解
- 19、基于不同业务的数据库表结构设计、性能优化案例
- 20、pymysql模块介绍和使用
修改表结构的语法
- 语法:
- 1. 修改表名
- ALTER TABLE 表名
- RENAME 新表名;
- 2. 增加字段
- ALTER TABLE 表名
- ADD 字段名 数据类型 [完整性约束条件…],
- ADD 字段名 数据类型 [完整性约束条件…];
- ALTER TABLE 表名
- ADD 字段名 数据类型 [完整性约束条件…] FIRST;
- ALTER TABLE 表名
- ADD 字段名 数据类型 [完整性约束条件…] AFTER 字段名;
- 3. 删除字段
- ALTER TABLE 表名
- DROP 字段名;
- 4. 修改字段
- ALTER TABLE 表名
- MODIFY 字段名 数据类型 [完整性约束条件…];
- ALTER TABLE 表名
- CHANGE 旧字段名 新字段名 旧数据类型 [完整性约束条件…];
- ALTER TABLE 表名
- CHANGE 旧字段名 新字段名 新数据类型 [完整性约束条件…];
1、创建一个表student,包含ID(学生学号),sname(学生姓名),gender(性别),credit(信用卡号),四个字段,要求:ID是主键,且值自动递增,sname是可变长字符类型,gender是枚举类型, credit是可变长字符类型;
- create table student(
- ID int primary key auto_increment,
- sname varchar(16) not null,
- gender enum('male','female') not null default 'female',
- credit varchar(32)
- );
2、在上面的student表中增加一个名为class_id的外键,外键引用class表的cid字段;
- create table class(
- cid int primary key auto_increment,
- cname varchar(16) not null
- );
- alter table student add class_id int not null;
- alter table student add foreign key(class_id) references class(cid) on delete cascade on update cascade;
3、向该表新增一条数据,ID为1,学生姓名为alex,性别女,修改ID为1的学生姓名为wupeiqi,删除该数据;
- insert into class(cname) values
- ('一班'),
- ('二班');
- insert into student values(1,'alex','female','12345',1);
- update student set sname = 'wupeiqi' where id = 1;
- delete from student where id = 1;
4、查询student表中,每个班级的学生数;
- insert into student(sname,class_id) values
- ('james',1),
- ('durant',2),
- ('curry',3);
- select count(ID) from student;
5、修改credit字段为unique属性;
- alter table student modify credit varchar(32) not null unique;
6、请使用命令在你本地数据库中增加一个用户,并给该用户授予创建表的权限;
- grant create on *.* to 'james'@'localhost' identified by '123';
7、请使用pymsql模块连接你本地数据库,并向student表中插入一条数据;
- # -*- coding:utf-8 -*-
- import pymysql
- conn = pymysql.connect(
- host = '127.0.0.1',
- port = 3306,
- user = 'root',
- password = '123',
- db = 'db_bj',
- charset = 'utf8'
- )
- cursor = conn.cursor()
- sql = 'insert into student(sname,credit,class_id) values (%s,%s,%s)'
- rows = cursor.execute(sql,('alcie','1234567',1))
- conn.commit()
- cursor.close()
- conn.close()
- if rows:
- print('success')
- else:
- print('failed')
8、请使用mysqldump命令备份student表;
- mysqldump -uroot -p123 db_bj student > /home/bj/桌面/myfile/student.sql
9、创建一张名为student_insert_log的表,要求每次插入一条新数据到student表时,都向student_insert_log表中插入一条记录,记录student_id, insert_time;
- mysql> desc student;
- +----------+-----------------------+------+-----+---------+----------------+
- | Field | Type | Null | Key | Default | Extra |
- +----------+-----------------------+------+-----+---------+----------------+
- | ID | int(11) | NO | PRI | NULL | auto_increment |
- | sname | varchar(16) | NO | | NULL | |
- | gender | enum('male','female') | NO | | female | |
- | credit | varchar(32) | NO | UNI | NULL | |
- | class_id | int(11) | NO | MUL | NULL | |
- +----------+-----------------------+------+-----+---------+----------------+
- create table student_insert_log(
- student_id int not null,
- insert_time datetime not null
- );
- 创建一个触发器:
- delimiter //
- create trigger tri_after_insert_student after insert on student for each row
- begin
- insert into student_insert_log values(new.ID,now());
- end //
- delimiter ;
- insert into student(sname,credit,class_id) values ('alice','123',2);
- insert into student(sname,credit,class_id) values
- ('egon1','1234',1),
- ('egon2','12345',2);
- mysql> select * from student;
- +----+-------+--------+---------+----------+
- | ID | sname | gender | credit | class_id |
- +----+-------+--------+---------+----------+
- | 4 | alcie | female | 123456 | 1 |
- | 7 | alcie | female | 1234567 | 1 |
- | 8 | alice | female | 123 | 2 |
- | 9 | egon1 | female | 1234 | 1 |
- | 10 | egon2 | female | 12345 | 2 |
- +----+-------+--------+---------+----------+
- mysql> select * from student_insert_log;
- +------------+---------------------+
- | student_id | insert_time |
- +------------+---------------------+
- | 8 | 2018-04-24 21:29:46 |
- | 9 | 2018-04-24 21:32:05 |
- | 10 | 2018-04-24 21:32:05 |
- +------------+---------------------+
- 10、创建一张名为student_update_log的表,要求每次更新student表中的记录时,都向student_update_log表中插入一条记录,记录student_id, update_time;
- create table student_update_log(
- student_id int not null,
- update_time datetime
- );
- 创建一个触发器
- delimiter //
- create trigger tri_after_update_student after update on student for each row
- begin
- insert into student_update_log values(new.ID,now());
- end //
- delimiter ;
- show triggers\G;
- update student set sname = 'alex' where ID in (9,10);
- mysql> select * from student;
- +----+-------+--------+---------+----------+
- | ID | sname | gender | credit | class_id |
- +----+-------+--------+---------+----------+
- | 4 | alcie | female | 123456 | 1 |
- | 7 | alcie | female | 1234567 | 1 |
- | 8 | alice | female | 123 | 2 |
- | 9 | alex | female | 1234 | 1 |
- | 10 | alex | female | 12345 | 2 |
- +----+-------+--------+---------+----------+
- 5 rows in set (0.00 sec)
- mysql> select * from student_update_log;
- +------------+---------------------+
- | student_id | update_time |
- +------------+---------------------+
- | 9 | 2018-04-24 21:47:24 |
- | 10 | 2018-04-24 21:47:24 |
- +------------+---------------------+