python 闖關之路四(下)(併發編程與數據庫編程)

併發編程重點:

併發編程:線程、進程、隊列、IO多路模型

操做系統工做原理介紹、線程、進程演化史、特色、區別、互斥鎖、信號、
事件、join、GIL、進程間通訊、管道、隊列。

生產者消息者模型、異步模型、IO多路複用模型、select\poll\epoll 高性
能IO模型源碼實例解析、高併發FTP server開發

一、請寫一個包含10個線程的程序,主線程必須等待每個子線程執行完成以後才結束執行,每個子線程執行的時候都須要打印當前線程名、當前活躍線程數量;html

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----')

二、請寫一個包含10個線程的程序,並給每個子線程都建立名爲"name"的線程私有變量,變量值爲「james」;python

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 ---')

三、請使用協程寫一個消費者生產者模型;mysql

協程知識點:http://www.javashuo.com/article/p-adknkdvb-ct.htmlsql

協程:單線程下,沒法利用多核,能夠是一個程序開多個進程,每一個進程開啓多個線程,每隔線程開啓協程;數據庫

  協程指的是單個線程,於是一旦協程出現阻塞,將會阻塞整個線程。編程

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()

四、寫一個程序,包含十個線程,子線程必須等待主線程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()

五、寫一個程序,包含十個線程,同時只能有五個子線程並行執行;服務器

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()

六、寫一個程序 ,包含一個名爲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()

七、寫一個程序,利用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('主')

八、寫一個程序,利用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())

九、使用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'))

十、使用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()

十一、請使用asyncio實現一個socket服務器端程序;

 十二、寫一個程序,使用socketserver模塊,實現一個支持同時處理多個客戶端請求的服務器,要求每次啓動一個新線程處理客戶端請求;

socketserver模塊類介紹
      SocketServer內部使用 IO多路複用 以及 「多線程」 和 「多進程」 ,
從而實現併發處理多個客戶端請求的Socket服務端。即:每一個客戶端請求
鏈接到服務器時,Socket服務端都會在服務器是建立一個「線程」或者「進 程」
 專門負責處理當前客戶端的全部請求。
        socketserver模塊能夠簡化網絡服務器的編寫,python把網絡服務抽
象成兩個主要的類,一個是server類,用於處理鏈接相關的網絡操做,另外一個
是RequestHandler類,用於處理數據相關的操做。而且提供兩個Mixln類,
用於擴展server,實現多進程或者多線程。

  

import socketserver
import threading


class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            self.data = self.request.recv(1024).decode()
            print(self.data)
            self.request.send(self.data.upper().encode())
        
        
if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('127.0.0.1', 9999), MyServer)
    t = threading.Thread(target=server.serve_forever)
    t.start()

  

數據庫重點:

一、數據庫介紹、類型、特性
二、MySQL數據庫安裝、鏈接、啓動、中止
三、表字段類型介紹、主鍵約束、表建立語句
四、經常使用增刪改查語句、分組、聚合
五、外鍵管理、unique字段、表結構修改語法
六、跨表查詢,inner join、left join、right join、full join語法
七、複雜SQL語句如group by、子查詢、函數的使用
八、索引原理及做用、普通索引、多列索引、惟一索引、全文索引等
九、基於hash&b+樹索引的實現原理,索引的優缺點剖析
十、事務原理,ACID特性,應用場景講解
十一、事務回滾
十二、觸發器的特性,應用場景
1三、觸發器的增刪改查方法
1四、存儲過程的做用及應用場景
1五、建立存儲過程,參數傳遞,流程控制語句if\while\repeat\loop等,動態SQL的建立
1六、視圖的做用及使用場景,視圖的增刪改查
1七、數據庫權限管理,用戶管理
1八、數據庫備份命令及工具講解
1九、基於不一樣業務的數據庫表結構設計、性能優化案例
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 舊字段名 新字段名 新數據類型 [完整性約束條件…];

  

一、建立一個表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)
);

  

二、在上面的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;

  

三、向該表新增一條數據,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; 

  

四、查詢student表中,每一個班級的學生數;

insert into student(sname,class_id) values
('james',1),
('durant',2),
('curry',3); 
select count(ID) from student;

  

五、修改credit字段爲unique屬性;

alter table student modify credit varchar(32) not null unique;

  

六、請使用命令在你本地數據庫中增長一個用戶,並給該用戶授予建立表的權限;

grant create on *.* to 'james'@'localhost' identified by '123';       

  

七、請使用pymsql模塊鏈接你本地數據庫,並向student表中插入一條數據;

# _*_ coding: utf-8 _*_ 
# 七、請使用pymsql模塊鏈接你本地數據庫,並向student表中插入一條數據;
import pymysql
conn = pymysql.connect(
    host = '127.0.0.1',
    port = 3306,
    user = 'root',
    password = '******',
    db = 'test622',
    charset = 'utf8'
)
cursor = conn.cursor()
sql = "insert into student values(13,'park','男','123456',1)"
rows = cursor.execute(sql)

conn.commit()
cursor.close()
conn.close()

  

八、請使用mysqldump命令備份student表;

mysqldump -uroot -p123 db_bj student > /home/bj/桌面/myfile/student.sql

  

九、建立一張名爲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 |
+------------+---------------------+
十、建立一張名爲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 |
+------------+---------------------+
相關文章
相關標籤/搜索