• python新手总结(二)


    random模块

    随机小数

    • random
    • uniform

    随机整数

    • randint
    • randrange

    随机抽取

    • choice
    • sample

    打乱顺序

    • shuffle

    random.random() 生成:0<n<1.0

    uniform(x,y) 一定范围的随机浮点数 (包左包右)

    random.uniform(x,y)
    

    randint(x,y) 随机整数 (包左包右)

    randrange(x,y,z) 随机整数(包左不包右)

    random.randrange(10,100,4) #输出为10到100内以4递增的序列[10,14,18,22...]
    

    choice(seq) 从序列中获取一个随机元素,参数seq表示有序类型,并不是一种特定类型,泛指list tuple 字符串等

    import random
    random.choice(range(10)) #输出0到10内随机整数
    random.choice(range(10,100,2)) #输出随机值[10,12,14,16...]
    random.choice("I love python") #输出随机字符I,o,v,p,y...
    random.choice(("I love python")) #同上
    random.choice(["I love python"]) #输出“I love python”
    random.choice("I","love","python") #Error
    random.choice(("I","love","python")) #输出随机字符串“I”,“love”,“python”
    random.choice(["I","love","python"]) #输出随机字符串“I”,“love”,“python”
    

    shuffle(list) 用于将一个列表中的元素打乱

    sample() 从指定序列中随机获取k个元素作为一个片段返回,sample不会改变原有序列

    a='1232445566'
    b=[1,2,3,4,4,5]
    print(random.sample(b,2))
    print(random.sample(a,2))
    

    time 时间模块

    time.strftime('%Y-%m-%d %H:%M:%S')
    

    sys模块

    sys 是与python解释器相关的

    sys.path 寻找文件的路径

    sys.modules 导入多少路径

    在编译器不能运行

    name=sys.argv[1]    # 有点类似input() 不过input是阻塞的
    pwd=sys.argv[2]
    if name='alex' and pwd =='alex3714':
    print('执行以下代码')
    else:
    	exit()
    

    os模块

    print(os.getcwd()) # 在哪个地方执行这个文件,getcwd的结果就是哪个路径
    
    removedirs
    递归向上删除文件夹,只要删除当前目录之后,发现上一级目录也为空了,就把上一级目录删除
    如果发现上一级目录有其他文件,就停止
    os.listdir() (重要)列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方法打印
    
    

    print(os.path.dirname(os.path.dirname(__file__)))#上一级再上一级目录,也就是工作区
    

    序列化

    得到一个字符串的结果,过程就叫序列化

    字典/列表/数字/对象 -序列化-->字符串

    为什么要序列化

    • 要把内容写入文件
    • 网络传输数据

    eval不能随便用

    dump dumps load loads

    import json
    dic={'aaa':'bbb','ccc':'ddd'}
    str_dic=json.dumps(dic)  # 序列化
    print(dic)
    print(str_dic,type(str_dic))
    with open('json_dump','w') as f:
    # f.write(str_dic)       # 反序列化
            json.dump(dic,f)
    ret=json.loads(str_dic)  # 反序列化
    print(ret,type(ret))
    
    with open('json_dump1') as f:
        print(type(json.load(f)))
    

    json的限制

    • json格式的key必须是字符串数据类型,如果是数字为key那么dump之后会强行转成字符串数据类型

    • json格式中的字符串只能是双引号

    • json是否支持元祖,对元组做value的字典会把元组强制转换成列表

    • dic={'abc':(1,2,3)}
      str_dic=json.dumps(dic)
      print(str_dic)
      
    • json是否支持元组做key,会报错

    pickle

    • pickle 支持几乎所有对象
    dic={1:(12,3,4),('a','b'):4}
    pic_dic=pickle.dumps(dic)# 序列化 看不见   bytes类型
    print(pic_dic)
    new_dic=pickle.loads(pic_dic)# 反序列化
    
    对于对象的序列化需要这个对象对应的类在内存中
    dump的结果是bytes, dump用的f文件句柄需要以wb的形式打开,load所用的f是'rb'模式
    with open('pickle_demo','wb') as f:
        pickle.dump(alex,f)
    with open('pickle_demo','rb') as f:
        wangcai=pickle.load(f)
        print(wangcai.name)
        
     with open('pickle_demo','rb') as f:
        while True:    # 不知道循环几次不能用for 用while
            try:
                print(pickle.load(f))
            except EOFError:
                break
                
    import shelve  # 不建议使用
    # 存值
    f=shelve.open("shelve_demo")
    f['key']={'k1':(1,2,3),'k2':'v2'}
    f.close()
    # 取值
    f=shelve.open('shelve_demo')
    content=f['key']
    f.close()
    print(content)
    

    加密md5 sha1

    # hashlib.md5()
    # hashlib.sha1()
    #md5是一个算法,32位的字符串 ,每个字符串是一个十六进制
    # sha1也是一个算法,40位的字符串,每个字符都是一个十六进制
    # 算法相对复杂  计算速度也慢
    md5_obj=hashlib.md5()
    md5_obj.update(s.encode('utf-8'))
    res=md5_obj.hexdigest()
    print(res,len(res),type(res))
    # 数据库 撞库
    
    # 加盐
    md5_obj=hashlib.md5("加盐".encode('utf-8'))
    md5_obj.update(s.encode('utf-8'))
    # 动态加盐
    username=input('username:')
    passwd=input('passwd')
    md5obj=hashlib.md5(username.encode('utf-8'))
    md5obj.update(passwd.encode('utf-8'))
    print(md5obj.hexdigest())
    

    configparser模块

    logging 模块

    功能

    • 日志格式的规范
    • 操作的简化
    • 日志的分级管理

    logging 模块的使用

    logging.basicConfig(level=logging.DEBUG)  #级别
    logging.debug('debug message') #调试模式
    logging.info('info message') # 基础信息
    logging.warning('warning message')# 警告
    logging.error('error message') # 错误
    logging.critical('critical message') # 严重错误
    basicConfig
    不能将一个log信息既能输出到屏幕上有输出到文件上
    
    # logger 对象的形式来操作日志文件
    # 创建一个logger对象
    logger=logging.getLogger()
    # 创建一个文件管理操作符
    fh=logging.FileHandler()
    # 创建一个屏幕管理操作符
    sh=logging.StreamHandler()
    # 创建一个日志输出的格式
    format1=logging.Formatter('%(asctime)s-%(name)s-%(lecelname))
    
    # 文件管理操作符 绑定一个格式
    sh.setFormatter(format1)
    # 屏幕管理操作符 绑定一个格式
    
    
    # logger对象 绑定 文件管理操作符
    # logger对象 绑定 屏幕管理操作符
    

    网络编程

    由于不同机器上的程序要通信,才产生了网络

    server 服务端

    client 客户端

    b/s 架构 ----> 统一入口 (解耦分支)

    b/s 和c/s 架构的关系

    • b/s架构师c/s架构的一种

    网关的概念

    • 局域网中的机器想要访问局域网外的机器,需要通过网关
    • 端口 找到的程序
    • 在计算机上,没一个需要网络通信的程序,都会开一个端口
    • 在同一时间只会有一个程序占用一个端口
    • 不可能在同一时间有两个程序占用同一个端口
    • 端口的范围0-65545,一般情况下8000之后的端口
    • ip 确定唯一一台机器
    • 端口--- 确定唯一的一个程序
    • ip+端口 找到唯一的一台机器上的唯一的一个程序

    tcp协议和udp协议

    这个全双工的通信将占用两个计算机之间的通信线路,直到它被一方或双方关闭为止

    arp地址 通过ip找mac

    ip协议属于网络osi 七层协议中的哪一层,网络层

    tcp协议 udp协议属于传输层

    arp 协议 属于数据链路层

    黏包问题 不知道客户端发送的数据的长度

    大文件的传输一定要按照字节读,每一次读固定的字节

    > 实现一个大文件的上传或者下载---
    
    server端
    import json
    import socket
    import struct
    
    sk=socket.socket()
    sk.bind(('127.0.0.1',8090))
    sk.listen()
    buffer=1024
    conn,addr=sk.accept()# 接受
    head_len=conn.recv(4)
    head_len=struct.unpack('i',head_len)[0]
    json_head=conn.recv(head_len).decode('utf-8')
    head=json.loads(json_head)
    filesize=head['filesize']
    with open(head['filename'],'wb') as f:
        while filesize:
            if filesize>=buffer:
                content=conn.recv(buffer)
                f.write(content)
                filesize-=buffer
            else:
                content=conn.recv(filesize)
                f.write(content)
                filesize=0
                break
    conn.close()
    sk.close()
    
    
    
    client端
    import json
    import socket
    import os
    import struct
    
    buffer = 1024
    sk = socket.socket()
    sk.connect(('127.0.0.1', 8090))
    
    head = {# 发送文件
        'filepath': r'文件路径',
        'filename': r'文件名',
        'filesize': None
    }
    file_path = os.path.join(head['filepath'], head['filename'])
    filesize = os.path.getsize(file_path)
    head['filesize'] = filesize
    json_head = json.dumps(head)  # 字典转成字符串
    bytes_head = json_head.encode('utf-8')  # 字符串转成bytes
    print(json_head)
    print(bytes_head)
    
    head_len = len(bytes_head)# 计算head长度
    pack_len = struct.pack('i', head_len)
    sk.send(pack_len)  # 先发报头的长度
    sk.send(bytes_head)
    with open(file_path, 'rb') as f:
        while filesize:
            if filesize > buffer:
                content = f.read(buffer)  # 每次读出来的内鹅绒
                sk.send(content)
                filesize -= buffer
            else:
                content = f.read(filesize)
                f.read(content)
                break
    
    
    
    # 解决黏包问题
        # 为什么会会出现黏包现象
        # 首先 只有在TCP协议中才会出现黏包现象
        # 是因为TCP协议是面向流的协议
        # 在发送的数据传输的过程中还有缓存机制避免数据丢失
        # 因此在连续发送小数据的时候,以及接受大小不符的时候都容易出现黏包现象
        # 本质还是因为我们在接受数据的时候不知道发送的数据的长短
    # 解决黏包问题
        # 在传输大量数据之前先告诉接受端要发送的数据大小
        # 如果想更漂亮的解决问题,可以通过struct模块来定制协议
    
    # struct 模块
        # pack  unpack
        # 模式:   'i'
        # pack之后的长度: 4个字节
        #unpack之后拿到的数据是一个元组:元组的第一个元素才是pack的值
    

    进程

    只有在运行当中的程序--进程

    进程是操作系统中资源分配的最小单位

    进程是怎么被调度的

    • 先来先服务算法 FCFS
    • 短作业优先算法
    • 时间片轮转算法
    • 多级反馈算法

    进程

    • 异步 只管调度 不等结果
    • 同步 调度之后 还一定要等到结果

    进程的状态

    • 就绪 运行 阻塞 

    多进程

    • 进程与进程之间是完全的数据隔离的

    •     # from multiprocessing import Process
          #
          # n=100
          # def func():
          #     global n
          #     n=n-1
          #     print(n)
          #
          # if __name__=='__main__':
          #     for i in range(10):
          #         p=Process(target=func)
          #         p.start()
          #     print('主进程:',n)
      

    start 开启一个进程

    join 用join 可以让主进程等待子进程结束

    守护进程p.daemon=True

    • 守护进程会随着主进程的代码执行结束而结束

    • 正常的子进程没有执行完的时候主进程要一直等着

    •     # 守护进程的进程的作用: 会随着主进程的代码的执行结束而结束,不会等待其他子进程
          # 守护进程 要在start之前设置
          # 守护进程中不能再开启子进程
          def cal_time():
              while True:
                  time.sleep(1)
                  print("过去了10秒")
          if __name__=='__main__':
              p=Process(target=cal_time())
              p.daemon=True  # 一定在开启进程之前设置 
              p.start()
              for i in range(100):
                  time.sleep(0.1)
                  print('*'*i)
      
        # p.is_alive() # 是否活着 True 代表进程还在False代表进程不在了
        # p.terminatr() # 结束一个进程但是这个进程不会立刻被杀死
        import time
        from multiprocessing import Process
    
        def func():
            print('wahaha')
            time.sleep(4)
            print('qqxing')
        if __name__=='__main__':
            p=Process(target=func)
            p.start()
            print(p.is_alive())
            p.terminate()       # 关闭进程 异步
            print(p.is_alive())
    # 属性
    # pid 查看这个进程  进程id
    # name 查看这个进程的名字
    class MyProcess(Process):
        def run(self):
            print('wahaha',self.name,self.pid)
            time.sleep(5)
            print('qqxing',self.name,self.pid)
    if __name__=='__main__':
        p= MyProcess()
        p.start()
        print(p.pid)
    

     lock.acquire() # 需要锁  拿钥匙
     lock.release() # 释放锁  还钥匙
     买票
    
    import random
    import time
    
    from multiprocessing import Lock
    from multiprocessing import Process
    def search(i):
        with open('ticket') as f:
            print(i,json.load(f)['count'])
    def get(i):
        with open('ticket') as f:
            ticket_num=json.load(f)['count']
        time.sleep(random.random())
        if ticket_num>0:
            with open('ticket','w') as f:
                json.dump({'count':ticket_num-1},f)
            print('%s买到票了'%i)
        else:
            print('%s没票'%i)
    def task(i,lock):
        search(i) #查看票
        lock.acquire()
        get(i)   #抢票
        lock.release()
    
    
    if __name__=='__main__':
        lock=Lock()
        for i in range(20):
            p=Process(target=task,args=(i,lock))
            p.start()
    

    信号量

    # 信号量
    import random
    import time
    from multiprocessing import Semaphore, Process
    
    
    # sem.acquire() # 需要钥匙
    # print(0)
    # sem.acquire() # 需要钥匙
    # print(1)
    # sem.acquire() # 需要钥匙
    # print(2)
    # sem.acquire() # 需要钥匙
    # print(3)
    # sem.acquire() # 需要钥匙
    # print(4)
    # 迷你唱吧 20个人 同一时间只能有4个人进去唱歌
    def sing(i,sem):
        sem.acquire()
        print('%s:进入 ktv'%i)
        time.sleep(random.randint(1,10))
        print('%s: 出来 ktv'%i)
        sem.release()
    if __name__=='__main__':
        sem = Semaphore(4)
        for i in range(20):
            Process(target=sing,args=(i,sem)).start()
    

    事件

    from multiprocessing import Event # 事件
    e=Event() # 实例化一个事件  标志/交通信号灯
    e.set()    # 将标志变成非阻塞/交通灯变绿
    e.wait()    # 刚实例化出来的一个事件对象,默认的信号是阻塞信号/默认是红灯
                # 执行到wait,要先看灯,绿灯行红灯停,如果在停的过程中,灯绿了,就变成非阻塞的
    e.clear() # 将标志又变成阻塞/交通灯变红
    e.is_set() # 是否则色 True 就是绿灯 False 就是红灯 
    
    # 红绿灯
    import time
    import random
    
    def triffic_lifht(e):
        while True:
            if e.is_set():
                time.sleep(3)
                print('红灯亮')
                e.clear()  # 绿变红
            else:
                time.sleep(3)
                print('绿灯亮')
                e.set()  # 红变绿
    
    def car(i, e):
        e.wait()
        print('%s车通过' % i)
    
    
    if __name__ == '__main__':
        e = Event()  # 立一个红灯
        tra = Process(target=triffic_lifht, args=(e,))
        tra.start()  # 启动一个进程来控制红绿灯
        for i in range(100):
            if i % 6 == 0:
                time.sleep(random.randint(1, 3))
            car_pro = Process(target=car, args=(i, e))
            car_pro.start()
    

    队列 Queue 管道+锁 双向通信 数据安全

    # 进程之间通信  可以使用multiprocessing 的Queue模块
    # 队列有两种创建方式 第一种不传参数 这个队列就没有长度限制;
    # 传参数,创建一个有最大长度限制的队列
    # 提供两个重要方法:put  get
    # qsize  不怎么准确
    
    def q_put(q):
        q.put('hello')
    
    def q_get(q):
        print(q.get())
    if __name__=='__main__':
        q=Queue()
        p=Process(target=q_put,args=(q,))
        p.start()
        p1=Process(target=q_get,args=(q,))
        p1.start()
    #通过队列实现了 主进程与子进程的通信 子进程与子进程之间的通信
    # 生产者消费者模型
    # 我要生产一个数据 然后给一个函数 让这个函数依赖这个数据进行运算,拿到结果--同步过程
    
    # 做包子和吃包子
    def producer(q):# 生产者
        for i in range(100):
            q.put('包子%s'%i)
    
    def couseumer(q): #消费者
        for i in range(100):
            time.sleep(1)
            print(q.get())
    
    if __name__=='__main__':
        q=Queue(10) # 托盘
        p=Process(target=producer,args=(q,))
        p.start()
        c=Process(target=couseumer,args=(q,))
        c.start()
        c1 = Process(target=couseumer, args=(q,))
        c1.start()
    首先 对于内存空间来说  每次只有很少的数据会在内存中
    对于生产与消费之间的不平衡来说
    * 增加消费者或者增加生产者来调用效率
    

    生产者-消费者模型(很重要)

    joinableQueue putget 的一个技术机制,每次get数据之后发送task_done.put端接收

    记数-1,直到计数为0就能感知到

    # # 消费者已经把生产的所有数据都处理完了
    # # 主进程 producer.join() 等待生产者结束
    # # 设置消费者为守护进程
    import time
    import random
    from multiprocessing import Process, JoinableQueue
    
    
    def produceer(q,food):
        for i in range(5):
            q.put('%s-%s'%(food,i))
            print('生产了%s'%food)
            time.sleep(random.random())
        q.join()  # 等待消费者把所有数据处理完
    def consumer(q,name):
        while True:
            food=q.get() # 生产者不生产还是生产的慢
            if food==None:break
            print('%s吃了%s'%(name,food))
            q.task_done()
    if __name__=='__main__':
        q=JoinableQueue()
        p1=Process(target=produceer,args=(q,'泔水'))
        p1.start()
        p2=Process(target=produceer,args=(q,'骨头'))
        p2.start()
        c1=Process(target=consumer,args=(q,'alex'))
        c1.daemon=True
        c1.start()
        c2=Process(target=consumer,args=(q,'sun'))
        c2.daemon=True
        c2.start()
        p1.join() # 等待p1执行完毕
        p2.join() # 等待p2执行完毕
    
    # 生产者生产的数据全部被消费---生产者进程结束
    # 主进程执行结束----消费者守护进程结束
    

    管道(不懂) Pipe 管道 双向通信 数据不安全

    # 用管道 也能实现 生产者消费者模型
    # socket  接受  
    # 等待数据
    # 数据发送到操作系统
    # 从操作系统copy到进程中
    
    # 队列=管道+锁
    # 双向通信
    # 数据不安全 ,没有锁的机制
    # 基于管道和锁 实现了队列---队列 用在同一台机器的多个进程之间通信
    

    进程之间的数据共享Manager

    • 但是数据是不安全的

    进程池 Pool

        # 进程池
        # 造一个池子 放4个进程(员工)来用来完成工作
        # 发任务
        # 循环使用池子中进程完成任务
        进程池为什么出现:开过多的进程1.开启进程浪费时间2.操作系统调度太多的进程也会影响效率
        开进程池: 有几个现成的进程在池子里,有任务来了,就用这个池子中的进程处理任务
        当所有的任务都处理完了,进程池关闭,回收所有的进程
    
        from multiprocessing import Pool
        # apply
        def func(i):
            i+=1
            return i
        if __name__=='__main__':
            p=Pool(5)
            res_l=[]
            for i in range(20):
                # p.apply(func,args=(i,)) # apply是同步提交任务的机制(几乎不用)
                res=p.apply_async(func,args=(i,)) # apply_async 是异步提交任务的机制
                res_l.append(res)
                print(res.get()) # 阻塞:等待着任务的结果
            p.close()# close必须加在join之前,不允许在添加新的任务了
            p.join()  # 等待子进程结束在往下执行
            [print(i.get()) for i in res_l]
    
        #apply_async
        import time
        from multiprocessing import Pool
        def func(i):
            time.sleep(1)
            i+=1
            return i
    
        if __name__=='__main__':
            p=Pool(4)
            res_l=[]
            for i in range(10):
                res=p.apply_async(func,args=(i,))# apply target
                res_l.append(res)
            p.close() # 不能再往进程池中添加新的任务
            p.join() # 阻塞等待 执行进程池中的所有任务直到执行结束
            [print(res.get()) for res in res_l]
    
        # map
        def fun(i):
            time.sleep(1)
            i+=1
            return i
        if __name__=='__main__':
            s=time.time()
            p=Pool(4)
            ret= p.map(fun,range(10)) # func(next(range(10))
            print(ret)
            print(time.time()-s)
    
        # 参数  概念 回调函数   主进程执行, 参数是子进程执行的函数的返回值
        # os.getpid()获取当前进程id     os.getppid()获取父进程id
        def func(i):  # 多进程中的io多
            print('子进程%s:%s'%(i,os.getpid))
            return i*'*'
    
        def call(arg):# 回调函数是在主进程中完成的,不能传参数,只能接受多进程中函数的返回值
            print('回调:',os.getpid())
            print(arg)
    
        if __name__=='__main__':
            print('---->',os.getpid())
            p=Pool(5)
            for i in range(10):
                p.apply_async(func,args=(i,),callback=call)
            p.close()
            p.join()
    

    线程

    进程是资源分配的最小单位,线程是CPU调度的最小单位

    每一个进程中至少有一个线程

    进程包含着线程

    GIL 全局解释器锁 Cpython解释器

    去掉GIL 保证数据安全 细粒度的锁 效率更低

    一个程序中可以开启多进程多线程

        import time
        from threading import Thread
        import os
        class MyThead(Thread):
            count = 0  # 静态属性
            def __init__(self,arg1,arg2):
                super().__init__()
                self.arg1=arg1
                self.arg2=arg2
            def run(self):
                MyThead.count += 1
                time.sleep(1)
                print('%s,%s,hello world,%s'%(self.arg1,self.arg2,os.getpid()))
    
    
        for i in range(10):
            t = MyThead(i,i*'*')
            t.start()
        # 计算开启的线程数量
        # 多个子线程 共享 这个数据
    
        import threading
        def func(i):
            time.sleep(0.5)
            print(i,threading.currentThread().name,threading.currentThread().ident)
            # 查看线程的默认名字,查看ident 线程id
            # currentThread 查看线程的默认属性
        for i in range(10):
            t=threading.Thread(target=func,args=(i,))
            t.start()
    
        print(threading.enumerate()) # 返回正在运行着线程列表
        print(threading.activeCount())# 统计当前有多少个线程
    
        # 守护线程
        import time
        from threading import Thread
        def func():
            print('开始执行子线程')
            time.sleep(3)
            print('子线程执行完毕')
    
        t=Thread(target=func)
        t.setDaemon(True)  # 进程设置守护进程,是一个属性 daemon=True
        t.start()
        t2=Thread(target=func)
        t2.start()
        t2.join()
        # 守护线程 守护进程都是等待主线程中的代码 执行完毕
        # t2=Thread(target=func)
        # t2=start() -->代码执行完毕
        # 守护线程就结束了
        # 主线程还没结束 等待t2继承执行
    
        from threading import RLock # 递归锁
        from threading import Lock # 互斥锁
        lock=RLock()  # 递归锁  可以被两次acquire
        # lock=Lock()
        lock.acquire() # 等着钥匙
        lock.acquire() # 等着钥匙
        print(123)
        lock.release()
        lock.release()
        # 递归锁 可以解决死锁问题 
        在多线程并发的情况下,同一个线程中,如果出现多次acquire 就可能产生死锁线程现象
    

    信号量

            面试题
        [[0, 0, 0, 0, 0], [0, 1, 2, 3, 4], [0, 2, 4, 6, 8], [0, 3, 6, 9, 12]]
        ret = [[i * j for j in range(5)] for i in range(4)]
        print(ret)
    
    
        面试题
        '''
        有一个文本
        https://y.qq.com/
        https://www.baidu.com/index.html
        https://www.bilibli.com/imd.html
        https://m.taobao.coom/cc.html
        https://y.qq.com/
        https://www.baidu.com/index.html
        https://www.bilibli.com/imd.html
        https://m.taobao.coom/cc.html
        https://qq.lol.com/index.html
        https://qq.lol.com/index.html
        '''
        '''
        脚本输出
        倒序次数 www.bilibilicom
        '''
        import re
        from collections import Counter
        with open('re.log') as f:
            data = f.read()
        ym_list=re.findall(r'https://(.*?)/.*?',data)
        tm_dict=dict(Counter(ym_list))
        #排序
        ret=sorted(ym_list.items(),key=lambda x:x[1],reverse=True)
        for i in ret:
            print(i[1],i[0])
    
        import random
        import time
        from threading import Semaphore, Thread
    
        sem=Semaphore(5)# 一把锁有5把钥匙
        def func(n,sem):
            sem.acquire()
            print('thread -%s'%n)
            time.sleep(random.random())
            print('thread -%s start'%n)
            sem.release()
        for i in range(20):
            Thread(target=func,args=(i,sem)).start()
    
        # 信号量和线程池有什么区别
        # 相同点
            #在aacquire之后,和线程池一样,同时在执行的只能有n个
        # 不同点
            #开的线程数不一样,线程池来说,一共就只能开5个线程,信号量有几个任务就开几个线程
        # 对有信号量限制的程序来说,可以同时执行很多线程么
        # 实际上 信号量并不影响线程或者进程的并发,只是在加锁的阶段进行流量限制
    

    事件

        # Event
        # flag标志
        # 刚刚创建的时候 flag=False
        # wait() flag=False 阻塞
        #       # flag=True 非阻塞
        # set() Fasle--> True
        # clear() True-->False
        # 连接mysql数据库
        # 我连接三次数据库
        # 每0.5秒连接一次
        # 创建一个事件,来标志数据库的连接情况
        # 如果连接成功就显示成功
        # 否则就报错
    
        def conn_mysql():  # 连接数据库
            count=0
            while not e.is_set():
                if count>3:
                    raise TimeoutError
                print('尝试连接第%s次'%count)
                count+=1
                e.wait(0.5) # 一直阻塞变成了只阻塞0.5
            print('连接成功')
        # 检测数据库的连接是否正常
        def check_conn():
        # 模拟连接检测的事件
            time.sleep(random.randint(1,2))# 检测
            e.set() # 告诉事件的标志数据库可以连接
    
        e=Event()
        check = Thread(target=check_conn)
        check.start()
        conn=Thread(target=conn_mysql)
        conn.start()
    
    	定时器
        from threading import Timer
    
        def hello():
            while True: # 这个线程一直在
                time.sleep(1)
                print("hello,world")
        while True: # 每隔一段时间要开启一个线程
            t=Timer(1,hello()) # 定时开启一个线程 ,执行一个任务
                            #定时: 多久之后,单位是s
                            # 要执行的任务: 函数名
    
        t.start()
        #sleep的时间
        # sleep的时间短 就在线程内while True
        # sleep的时间长 就在主线程while True 
    
        # 条件    condition  notify_all notify 
        def run(n):
            con.acquire()
            con.wait() # 等着
            print("run the thread :%s"%n)
            con.release()
        if __name__=='__main__':
            con=threading.Condition()
            for i in range(10):
                t=threading.Thread(target=run,args=(i,))
                t.start()
    
            while True:
                inp=input('>>>')
                if inp=='q':
                    break
                con.acquire()# condition中的锁是递归锁
                if inp=='all':
                    con.notify_all()
                else:
                    con.notify(int(inp)) #传递信号notify(1) 可以放行一个线程
                con.release()
    
    	# 优先级
        import queue
        # q=queue.Queue() # 队列 线程安全的
        #q.get()
        #q.put()
        #q.qsize()
    
        lfq=queue.LifoQueue() # 后进先出 :栈
        lfq.put(1)
        lfq.put(2)
        lfq.put(3)
        lfq.put(4)
        print(lfq.get())
        print(lfq.get())
        print(lfq.get())
        print(lfq.get())
    
        pq=queue.PriorityQueue() #值越小越优先,值相同就先进先出
        pq.put((10,'a'))
        pq.put((5,'b'))
        pq.put((4,'c'))
        pq.put((6,'d'))
    
        print(pq.get())
    

    线程池

        # 线程池
        # 线程池和进程池
        # 是用来做池操作的最近新的模块
    
        # 开启线程需要成本 成本就开启进程要低
        # 高IO的情况下 开多线程
        # 所以我们不能开启任意多个线程
        # 开启线程池
    
        # futures.ThreadPoolExecutor # 线程池
        # futures.ProcessPoolExecutor #进程池
    
        from concurrent import futures
        def funcname(n):
            print(n)
            time.sleep(random.randint(1,3))
            return n*'*'
    
    
        threading_pool=futures.ThreadPoolExecutor(5)
        # threading_pool.map(funcname,range(10)) # map天生异步,接受可迭代对象的数据,不支持返回值
        # f_lst=[]
        # for i in range(10):
        #     f=threading_pool.submit(funcname,i) # submit 合并了创建线程对象和start的功能
        #     f_lst.append(f)
        # threading_pool.shutdown() #close() join()
        # [print(i.result()) for i in f_lst] # 一定按照顺序出结果
        #                             #f.result() 阻塞 等f执行完得到结果
        # 回调函数 add_done_callback(回调函数的名字)
        def call(args):
            print(args.result())
        threading_pool.submit(funcname,1).add_done_callback(call)
        # 统一了入口和方法,简化了操作,降低了学习的时间成本
    

    (gevent先放放,3.7安装不上)

        协程
        # from greenlet import greenlet  # 在单线程中切换状态的模块
        # import time
        #
        # def eat1():
        #     print("吃鸡腿1")
        #     g2.switch()
        #     time.sleep(5)
        #     print("吃鸡翅2")
        #     g2.switch()
        #
        #
        # def eat2():
        #     print("吃饺子1")
        #     g1.switch()
        #     time.sleep(3)
        #     print('白切鸡')
        #
        #
        # g1 = greenlet(eat1)
        # g2 = greenlet(eat2)
        # g1.switch()
        # gevent 内部封装了greenlet模块
        # 切换不能规避IO时间
        # 协程的切换与正常程序的执行那个效率高
    

    IO模型

    阻塞IO: 工作效率低

    非阻塞IO:工作效率高,CPU的负担

    IO多路复用: 在有多个对象需要IO阻塞的时候,能够有效的减少阻塞带来的时间消耗,且能够在一定程度上减少CPU的负担(比较好的)

    异步IO: asyncio 异步IO 工作效率高 CPU的负担少


    MySQL

    mysql: 是用于管理文件的一个软件

    • 服务器软件
      • socket服务器
      • 本地文件操作
    • 客户端软件
      • socket客户端
      • 发送指令

    初始化:

    • 服务端 mysqld -- initialize-inzecure
    • 用户名root 密码:空

    启动服务端

    • mysqld

    客户端连接

    • mysql -u root -p

    发送命令:

    show databases;
    create database db1;
    

    配置环境变量: 安装包的 bin配置

    安装window服务

    H:mysql-5.7.24-winx64inmysqld --install

    H:mysql-5.7.24-winx64inmysqld --remove

    启动服务

    net start mysql

    net stop mysql

    操作文件夹
    	create database db2;
    	create database db2 default charset utf8;
    	show databases;
    	drop database db2;
    操作文件
    	show tables;
    	create table t1(
    		列名 类型 null,
    		列名 类型 not null,
    		列名 类型 not null default 1,
    		列名 类型 not null auto_increment primary key,
            id int,
            name char(10)
    	) default charset=utf8;
    	create table t1(id int,name char(10)) engine=innodb default charset=utf8;
    	#innodb 支持事物
    	auto_increment 表示:自增
    	primary key: 表示 约束(不能为空) 加速查找
    	数字:
    		tinyint
    		int
    		bigint
    		FLOAT(float)
    		DOUBLE(double)
    		decimal(底层原理 按字符串存的数字 标准)
    	字符串:
    		char(长度)  速度快
    		varchar(长度) 节省空间
    		ps: 创建定长char的列往前方,
    		text
    清空表
    	delete from t1;
    	truncate table t1;
    删除表:
    	delete from t1 where id<6;
    	drop table t1;
    修改:
    	update t1 set age=18;
    操作文件中内容
    	插入数据
    		insert into t1(id,name) values(1,'alex')
    查看数据库
    select * from t1;
    时间类型:
    DATETIME(datetime)
    enum(多选一)
    set(多选多)
    外键:
    	create table userinfo(
    		uid bigint auto_increment prinmary key,
    		name varchar(32),
    		department_id int,
    		constranint fk_user_depar foreign key ("department_id",) references department('id')
    	)
    	create table department(
    		id bigint auto_increment primary key,
    		title char(15)
    	)engine=innodb default charset=utf8;
    

    bootCDN

    小马哥

    武sir

    where

    • 关键字like 模糊查询

    • % _

    • in(100,200,300) not and or

    • between 9000 and 100
      

    group by 分组查询

    • 聚合函数

      max()最大值

      min() 最小值

      avg() 平均值

      sum() 求和

      count() 求总个数

      必须使用group by 才能使用group_concat()函数,将所有的name值连接

    having 过滤

    优先级   where>group by> having
    

    order by 查询排序

    select * from employee order by age ASC  升序
    select * from employee order by age DESC 降序
    

    limit 限定查询记录数(分页查询)

    SELECT * FROM employee ORDER BY salary DESC
            LIMIT 0,5; #从第0开始,即先查询出第一条,然后包含这一条在内往后查5条
    

    查看表结构和数据

    desc 表名;
    select * from  表名;
    

    多表查询

    表名1 join 表名2 on 条件

    select employee.id,employee.name,employee.age,employee.sex,department.name from employee inner join department on employee.dep_id=department.id;
    

    exists 关键字查询表示存在,

    • 当返回True时,外层查询语句进行查询,当返回值为false时,外层查询语句不进行查询
  • 相关阅读:
    行转列问题
    Session对象失效的客户端解决方法
    Spring之依赖注入
    Spring开发入门
    非关系型数据库redis
    Json(JavaScript Object Notation)
    Ajax
    JavaScript框架之JQuery
    Web核心之Filter过滤器
    Web核心练习之分页模块和条件模块(后台代码为主,jsp已经落伍)
  • 原文地址:https://www.cnblogs.com/fangdongdemao/p/9984727.html
Copyright © 2020-2023  润新知