经验拾忆(纯手工)=> Python三

发布时间:2019-10-08 20:14:23编辑:auto阅读(1945)

    GIL的理解

    GIL这个话题至今也是个争议较多的,对于不用应用场景对线程的需求也就不同,说下我听过的优点:
    1. 我没有用过其他语言的多线程,所以无法比较什么,但是对于I/O而言,Python的线程还是比较高效的。
    2. 有些第三方基于Python的框架和库,比如Tensorflow等基于C/C plus plus重写的Python线程机制。
    3. 至于换成Cython编译器解决GIL,这个只是听过,没用过。
    4. Python多线程对于web、爬虫方面也可以表现出较好的性能。
    5. Python多进程是完好的,可以把资源消耗较少的非必要线程工作转为多进程来工作。
    6. 计算密集型就别想多线程了,一律多进程。
    7. Python还有细粒度且高效的协程。
    8. 如果有N核CPU,那么同时并行的进程数就是N,每个进程里面只有一个线程能抢到工作权限。
       所以同一时刻最大的并行线程数=进程数=CPU的核数(这条我的个人理解很模糊,参考吧)

    多线程

    多线程有2种通过start的那种方式,非常普遍,此处就不写了。
    新版线程池 future库 是python3.2新出的功能(记住这个future)
    方式1:(sublime运行后直接贴上来了)
        from time import sleep
        from concurrent.futures import ThreadPoolExecutor,as_completed,ALL_COMPLETED,wait
        
        executor = ThreadPoolExecutor(max_workers=10)        # 初始化线程池10个坑
        def f():
            sleep(15)
            return 100
        all_tasks = [executor.submit(f) for _ in range(10)]  # 提交10个线程,全放池里执行
        # for per_thread in as_completed(all_tasks):         
            # print(per_thread.result())
        ---------# 注意上面,as_completed(all_tasks) 是等待future对象完成后才执行主线程
        ---------# 注意下面,wait和 as_completed() 的 作用一样,就和普通版的join() 相似
        for per_thread in all_tasks:
            print(per_thread.result())
        wait(all_tasks, return_when=ALL_COMPLETED)   # 还可以选FIRST_COMPLETED,待第一个完成后
        print('主线程')
            
    方式2: map多线程版
        value_list = executor.map(func, list(range(10))) # 返回的直接是map后的序列
        for value in value_list:
            print(value)
        注意:    
            这个map方式,如果要传多个参数就涉及到高阶函数那节讲的偏函数了。

    多进程

    多进程有2种通过start的那种方式+普通进程池,同样非常普遍,此处就不写了,自己百度一下。
    新版进程池 同样是和上面用一样的future库,惊不惊喜。(可以看出好的程序要向着统一封装的方向优化)
    也许你会惊讶,因为只把thread单词改为processing就是进程池版本了,就是这么简单!!!!!
    from time import sleep
    import multiprocessing
    from concurrent.futures import ProcessPoolExecutor,as_completed,ALL_COMPLETED,wait
    executor = ProcessPoolExecutor(max_workers=multiprocessing.cpu_count())
    def f():
        sleep(15)
        return 100
    
    if __name__ == '__main__':    # 这句要加
        all_tasks = [executor.submit(f) for _ in range(multiprocessing.cpu_count())]
        for per_thread in as_completed(all_tasks):
            print(per_thread.result())
        # for per_thread in all_tasks:
        #     print(per_thread.result())
        # wait(all_tasks, return_when=ALL_COMPLETED)
        print('主进程')   
    # 这就是 futures 模块 设计思想的魅力
    

    多协程

    前言:
        也许你记得,函数用到 yield 来代替 return 就变成了 生成器。其特点是代码片段断点式执行。
        如果有多个yield, 就可以自己用程序来切换执行程序。(这就是协程的特点)
    推荐:(学习中。。。)
        此笔者写的很好:
        https://juejin.im/post/5ccf0d18e51d453b557dc340
        
        

关键字