栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

python并发编程笔记5

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

python并发编程笔记5

python并发编程笔记5

是根据蚂蚁学Python的视频做的笔记,方便自己后续回顾

视频链接:BV1bK411A7tV

老师的源码

这一份笔记对应的是视频的P7-P8

文章目录
  • python并发编程笔记5
  • P7-Python好用的线程池ThreadPoolExecutor
    • 1、线程池的原理
      • 1.1、线程的生命周期
      • 1.2、线程池是怎么流转的呢
    • 2、使用线程池的好处
      • 2.1、提升性能:
      • 2.2、适用场景:
      • 2.3、防御功能:
      • 2.4、代码优势:
    • 3、ThreadPoolExecutor的使用语法
      • 前提:导入对应模块
      • 用法1:map函数
      • 用法2:future模式
    • 4、使用线程池改造爬虫程序
      • 注意事项:
      • 代码:
    • 总结:
  • P8-Python使用线程池在Web服务中实现加速
    • 1、Web服务的架构以及特点
      • Web后台服务的特点:
    • 2、使用线程池ThreadPoolExecutor加速
      • 使用线程池ThreadPoolExecutor的好处:
    • 3、代码用Flask实现Web服务并实现加速
    • 总结:

P7-Python好用的线程池ThreadPoolExecutor 1、线程池的原理 1.1、线程的生命周期

新建线程系统需要分配资源、终止线程系统需要回收资源

如果可以重用线程,则可以减去新建/终止的开销

1.2、线程池是怎么流转的呢

由两部分组成

线程池:里面是提前预先建好的线程,线程会被重复使用

任务队列:新的任务而不是直接创建线程

线程池会将任务队列的任务挨个取出依次执行,任务执行完后会取下一个任务执行,若没有任务,则回到线程池,不会进行销毁

2、使用线程池的好处 2.1、提升性能:

因为减去了大量新建、终止线程的开销,重用了线程资源;

2.2、适用场景:

适合处理突发性大量请求或需要大量线程完成任务、但实际任务处理时间较短

2.3、防御功能:

能有效避免系统因为创建线程过多,而导致系统负荷过大相应变慢等问题

2.4、代码优势:

使用线程池的语法比自己新建线程执行线程更加简洁

3、ThreadPoolExecutor的使用语法 前提:导入对应模块
from concurrent.futures import ThreadPoolExecutor,as_completed
用法1:map函数

很简单,注意map结果和入参是顺序对立的(指results 与 urls的顺序是一一对应的)

pool.map(函数,列表)会自动创建和列表等数量(不确定)的线程来处理。

with ThreadPoolExecutor() as pool:
    
    # 传入一个函数名(craw),和参数列表(urls)
    results = pool.map(craw, urls)
    
    for result in results:
        print(result)
用法2:future模式

更强大,注意如果用as——completed顺序是不定的

with ThreadPoolExecutor() as pool:
    
    # 传入的是单个url,而不是urls,返回的是一个future对象,放进一个futures里面
    futures = [ pool.submit(craw, url)
                for url in urls ]
    
    # 结果两种遍历方式
    # 会根据urls的对应顺序挨个获取future,并且获取结果
    for future in futures:
        print(future.result())
    
    # as_completed方式,好处:哪个任务先执行完了就先返回
    for future in as_completed(futures):
        print(future.result())
4、使用线程池改造爬虫程序 注意事项:

视频作者的代码讲的比较快,一些基础我这里普及一下

代码中使用的

zip方法是将urls与对应的的htmls新包为一个元组。

fufturs字典也是为存储跟上述相似的对应关系。

zip实例:

url_list = [1, 2, 3, 4]
html_list = ["a", "b", "c", "d"]
html_list = list(zip(url_list, html_list))
print(html_list)
for url, html in html_list:
    print(url, len(html))

结果:

[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]
1 1
2 1
3 1
4 1

代码:
import concurrent.futures
import blog_spider

# craw,使用map方法调用线程池
with concurrent.futures.ThreadPoolExecutor() as pool:
    htmls = pool.map(blog_spider.craw, blog_spider.urls)
    htmls = list(zip(blog_spider.urls, htmls))
    for url, html in htmls:
        print(url, len(html))

print("craw over")

# parse 使用future模式调用线程池

with concurrent.futures.ThreadPoolExecutor() as pool:
    futures = {}
    for url, html in htmls:
        future = pool.submit(blog_spider.parse, html)
        # 加入到字典的是好处url与future有对应关系
        futures[future] = url

    # 得到结果 有序的,等所有任务执行完了再返回
    # for future, url in futures.items():
    #     print(url, future.result())

    # as_completed方式,好处:哪个任务先执行完了就先返回,相比上面这个是无序的
    for future in concurrent.futures.as_completed(futures):
        url = futures[future]
        print(url, future.result())


总结:

使用这种map或者future模式比02中使用for循环实现thread好用的多

P8-Python使用线程池在Web服务中实现加速 1、Web服务的架构以及特点 Web后台服务的特点:

1、Web服务对响应时间要求非常高,比如要求200MS返回

2、Web服务有大量的依赖IO操作的调用,比如磁盘文件、数据库、远程API(暗示使用线程池来加速)

3、Web服务经常需要处理几万人、几百万人的同时请求(不能无限的创建线程池子)

2、使用线程池ThreadPoolExecutor加速 使用线程池ThreadPoolExecutor的好处:

1、方便的将磁盘文件、数据库、远程API的IO调用并发执行

2、线程池的线程数目不会无限创建(导致系统挂掉),具有防御功能

3、代码用Flask实现Web服务并实现加速
import flask
import json
import time
from concurrent.futures import ThreadPoolExecutor

app = flask.Flask(__name__)
pool = ThreadPoolExecutor()

def read_file():
    time.sleep(0.1)
    return "file result"


def read_db():
    time.sleep(0.2)
    return "db result"


def read_api():
    time.sleep(0.3)
    return "api result"


# @app.route("/")
# def index():
#     result_file = read_file()
#     result_db = read_db()
#     result_api = read_api()
#
#     return json.dumps({
#         "result_file": result_file,
#         "result_db": result_db,
#         "result_api": result_api,
#     })

@app.route("/")
def index():
    result_file = pool.submit(read_file)
    result_db = pool.submit(read_db)
    result_api = pool.submit(read_api)

    return json.dumps({
        "result_file": result_file.result(),
        "result_db": result_db.result(),
        "result_api": result_api.result(),
    })



if __name__ == '__main__':
    app.run()
总结:

通过线程池加速Web服务

全局中创建一个pool对象,用submit获取file对象,用result获取结果

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/879312.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号