• python 闯关之路四(下)(并发编程与数据库编程) 并发编程重点


    python 闯关之路四(下)(并发编程与数据库编程)

     

    并发编程重点:

    1
    2
    3
    4
    5
    6
    7
    并发编程:线程、进程、队列、IO多路模型
     
    操作系统工作原理介绍、线程、进程演化史、特点、区别、互斥锁、信号、
    事件、join、GIL、进程间通信、管道、队列。
     
    生产者消息者模型、异步模型、IO多路复用模型、selectpollepoll 高性
    能IO模型源码实例解析、高并发FTP server开发

    1、请写一个包含10个线程的程序,主线程必须等待每一个子线程执行完成之后才结束执行,每一个子线程执行的时候都需要打印当前线程名、当前活跃线程数量;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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 in range(10):
            = Thread(target=task,args=(i,))
            t.start()
            t_li.append(t)
        for in t_li:
            t.join()
             
        print('主,end----')

    2、请写一个包含10个线程的程序,并给每一个子线程都创建名为"name"的线程私有变量,变量值为“james”;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    from threading import Thread
    def task(name):
        print('%s is running'%name)
        print('end ---')
         
    if __name__ == "__main__":
        for in range(10):
            = Thread(target=task,args=('james_%s'%i,))
            t.start()
             
        print('主 end ---')

    3、请使用协程写一个消费者生产者模型;

    协程知识点:https://www.cnblogs.com/wj-1314/p/9040121.html

    协程:单线程下,无法利用多核,可以是一个程序开多个进程,每个进程开启多个线程,每隔线程开启协程;

      协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    def consumer():
        while True:
            = yield
            print('消费:', x)
             
    def producter():
        = consumer()
        next(c)
        for in range(10):
            print('生产:', i)
            c.send(i)
             
    producter()

    4、写一个程序,包含十个线程,子线程必须等待主线程sleep 10秒钟之后才执行,并打印当前时间

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    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 in range(10):
            = Thread(target=task)
            t.start()
             
        time.sleep(10)
        event.set()

    5、写一个程序,包含十个线程,同时只能有五个子线程并行执行;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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 in range(10):
            = Thread(target=task,args=(i,))
            t.start()

    6、写一个程序 ,包含一个名为hello的函数,函数的功能是打印字符串“Hello, World!”,该函数必须在程序执行30秒之后才开始执行(不能使用time.sleep());

    1
    2
    3
    4
    5
    6
    7
    from threading import Timer
    def hello(name):
        print('%s say '%name,'Hello World!')
         
    if __name__ == "__main__":
        = Timer(5,hello,args=('james',))
        t.start()

    7、写一个程序,利用queue实现进程间通信;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    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 in range(5):
            print('生产:',i)
            time.sleep(1)
            q.put(i)
             
    if __name__ == "__main__":
        = 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 in range(5):
            print('生产:',i,'--',current_process().name)
            time.sleep(1)
            q.put(i)
        q.join()
         
    if __name__ == "__main__":
        = 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实现进程间通信;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    from multiprocessing import Process,Pipe
    def task(conn):
        conn.send('hello world')
        conn.close()
         
    if __name__ == "__main__":
        parent_conn,child_conn = Pipe()
        = Process(target=task,args=(child_conn,))
        p.start()
        p.join()
        print(parent_conn.recv())

    9、使用selectors模块创建一个处理客户端消息的服务器程序;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    # 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或者线程服务器,一个潜在的问题是,恶意的程序可能会发送大量的请求导致服务器崩溃,请写一个程序,避免此类问题;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # 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服务器端程序;

     12、写一个程序,使用socketserver模块,实现一个支持同时处理多个客户端请求的服务器,要求每次启动一个新线程处理客户端请求;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    socketserver模块类介绍
          SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,
    从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求
    连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进 程”
     专门负责处理当前客户端的所有请求。
            socketserver模块可以简化网络服务器的编写,python把网络服务抽
    象成两个主要的类,一个是server类,用于处理连接相关的网络操作,另一个
    是RequestHandler类,用于处理数据相关的操作。并且提供两个Mixln类,
    用于扩展server,实现多进程或者多线程。

      

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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)
        = threading.Thread(target=server.serve_forever)
        t.start()

      

    数据库重点:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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、创建存储过程,参数传递,流程控制语句ifwhile epeatloop等,动态SQL的创建
    16、视图的作用及使用场景,视图的增删改查
    17、数据库权限管理,用户管理
    18、数据库备份命令及工具讲解
    19、基于不同业务的数据库表结构设计、性能优化案例
    20、pymysql模块介绍和使用

    修改表结构的语法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    语法:
    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是可变长字符类型;

    1
    2
    3
    4
    5
    6
    create table student(
        ID int primary key auto_increment,
        sname varchar(16not null,
        gender enum('male','female'not null default 'female',
        credit varchar(32)
    );

      

    2、在上面的student表中增加一个名为class_id的外键,外键引用class表的cid字段;

    1
    2
    3
    4
    5
    6
    7
    create table class(
        cid int primary key auto_increment,
        cname varchar(16not 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,删除该数据;

    1
    2
    3
    4
    5
    6
    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表中,每个班级的学生数;

    1
    2
    3
    4
    5
    insert into student(sname,class_id) values
    ('james',1),
    ('durant',2),
    ('curry',3);
    select count(IDfrom student;

      

    5、修改credit字段为unique属性;

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

      

    6、请使用命令在你本地数据库中增加一个用户,并给该用户授予创建表的权限;

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

      

    7、请使用pymsql模块连接你本地数据库,并向student表中插入一条数据;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # _*_ coding: utf-8 _*_
    # 7、请使用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()

      

    8、请使用mysqldump命令备份student表;

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

      

    9、创建一张名为student_insert_log的表,要求每次插入一条新数据到student表时,都向student_insert_log表中插入一条记录,记录student_idinsert_time;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    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 triggersG;
         
    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 |
    +------------+---------------------+
  • 相关阅读:
    访问 IIS 元数据库失败 的解决方法
    【转】IIS网站访问需要输入用户名和密码
    jQuery以Post方式发送请求并获取返回的文件供下载!
    moss2007安装
    货币加逗号 javascript/js
    vs2005 sp1 安装包签名错误解决办法 fid=73863 error 1718
    xpath ignore case query/xpath 不区分大小写
    moss2007 webpart custom property sample
    字符转拼音 javascript pinyin
    moss2007 webpart custom property sample (2) [a simple one, inherit from .net framework webpart]
  • 原文地址:https://www.cnblogs.com/anzhangjun/p/9459131.html
Copyright © 2020-2023  润新知