在Python 的线程中运行协程的方法

 更新时间:2020年02月24日 12:24:40   作者:kingname  
这篇文章主要介绍了在Python 的线程中运行协程的方法,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

在一篇文章 理解Python异步编程的基本原理 这篇文章中,我们讲到,如果在异步代码里面又包含了一段非常耗时的同步代码,异步代码就会被卡住。

那么有没有办法让同步代码与异步代码看起来也是同时运行的呢?方法就是使用事件循环的.run_in_executor()方法。

我们来看一下 Python 官方文档[1]中的说法:

那么怎么使用呢?还是以非常耗时的递归方式计算斐波那契数列的这个函数为例:

def sync_calc_fib(n): 
 if n in [1, 2]: 
 return1 
 return sync_calc_fib(n - 1) + sync_calc_fib(n - 2) 
async def calc_fib(n): 
 result = sync_calc_fib(n) 
 print(f'第 {n} 项计算完成,结果是:{result}') 
 return result 

我们现在需要用 aiohttp 访问一个延迟5秒的网页,同时计算斐波那契数列第36项。

首先我们看看单独计算第36项需要5秒钟:

我们再来看看如果直接把这计算斐波那契数列和请求网站的两个异步任务放在一起“并行”,实际时间是两个任务的时间叠加:

具体原因我在上一篇文章里面已经做了说明。

现在,我想让两个任务“同时运行”,于是就可以这样修改代码:

import aiohttp 
import asyncio 
import time 
from concurrent.futures import ThreadPoolExecutor 
async def request(sleep_time): 
 async with aiohttp.ClientSession() as client: 
 resp = await client.get(f'http://127.0.0.1:8000/sleep/{sleep_time}') 
 resp_json = await resp.json() 
 print(resp_json) 
def sync_calc_fib(n): 
 if n in [1, 2]: 
 return 1 
 return sync_calc_fib(n - 1) + sync_calc_fib(n - 2) 
def calc_fib(n): 
 result = sync_calc_fib(n) 
 print(f'第 {n} 项计算完成,结果是:{result}') 
 return result 
async def main(): 
 start = time.perf_counter() 
 loop = asyncio.get_event_loop() 
 with ThreadPoolExecutor(max_workers=4) as executor: 
 tasks_list = [ 
  loop.run_in_executor(executor, calc_fib, 36), 
  asyncio.create_task(request(5)) 
 ] 
 await asyncio.gather(*tasks_list) 
 end = time.perf_counter() 
 print(f'总计耗时:{end - start}') 
asyncio.run(main()) 

运行效果如下图所示:

在5秒钟的时间,就把计算斐波那契数列和请求5秒延迟的网站都做完了。

实现这样的转变,关键的代码就是:loop.run_in_executor(executor, calc_fib, 36)

其中的 loop就是主线程的事件循环(event loop),它是用来调度同一个线程里面的多个协程。

executor是我们使用ThreadPoolExecutor(max_workers=4)创建的一个有4个线程的线程池,calc_fib是一个耗时的同步函数,36是传入calc_fib的参数。loop.run_in_executor(executor, calc_fib, 36)的意思是说:

  • 把calc_fib函数放到线程池里面去运行
  • 给线程池增加一个回调函数,这个回调函数会在运行结束后的下一次事件循环把结果保存下来。

请注意上图中红色箭头对应的calc_fib这是一个同步函数,请与上一篇文章中的异步函数区分开。run_in_executor的第二个参数需要是一个同步函数的函数名。

在上面的例子中,我们创建的是有4个线程的线程池。所以这个线程池最多允许4个阻塞式的同步函数“并行”。

总结

到此这篇关于在Python 的线程中运行协程的方法的文章就介绍到这了,更多相关python线程中运行协程内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python实现定时任务的八种方案详解

    Python实现定时任务的八种方案详解

    在日常工作中,我们常常会用到需要周期性执行的任务,我们可以用Python直接实现这一功能。本文整理的是常见的Python定时任务的八种实现方式,需要的朋友可以参考一下
    2022-02-02
  • python判断字符串是否包含子字符串的方法

    python判断字符串是否包含子字符串的方法

    这篇文章主要介绍了python判断字符串是否包含子字符串的方法,实例分析了Python中的in与find方法来实现这一功能,非常具有实用价值,需要的朋友可以参考下
    2015-03-03
  • 用Python爬取指定关键词的微博

    用Python爬取指定关键词的微博

    这篇文章主要介绍了用Python爬取指定关键词的微博,下面文章围绕Python爬取指定关键词的微博的相关资料展开详细内容,需要的朋友可以参考一下
    2021-11-11
  • 详解Python验证码识别

    详解Python验证码识别

    这几天在写一个程序的时候需要识别验证码,因为程序是Python写的自然打算用Python进行验证码的识别。下面把实现思路分享在脚本之家平台,感兴趣的朋友可以参考下
    2016-01-01
  • python统计字母、空格、数字等字符个数的实例

    python统计字母、空格、数字等字符个数的实例

    今天小编就为大家分享一篇python统计字母、空格、数字等字符个数的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-06-06
  • python如何爬取网站数据并进行数据可视化

    python如何爬取网站数据并进行数据可视化

    这篇文章主要介绍了python爬取拉勾网数据并进行数据可视化,爬取拉勾网关于python职位相关的数据信息,并将爬取的数据已csv各式存入文件,然后对csv文件相关字段的数据进行清洗,并对数据可视化展示,包括柱状图展示、直方图展示,需要的朋友可以参考下
    2019-07-07
  • 使用PyTorch常见4个错误解决示例详解

    使用PyTorch常见4个错误解决示例详解

    这篇文章主要为大家介绍了使用PyTorch常见4个错误解决示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • Python自动化办公之创建PPT文件

    Python自动化办公之创建PPT文件

    python-pptx模块是Python中用于PPT操作的模块。本文将利用这一模块实现创建PPT文件。文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2022-05-05
  • selenium获取元素定位的方法总结(动态获取元素)

    selenium获取元素定位的方法总结(动态获取元素)

    要想操作一个元素,首先应该识别这个元素,人有各种的特征(属性),可以通过其特征找到人,同理,界面的某个元素会有各种的特征(属性),可以通过这个属性找到这对象,本文给大家介绍了python selenium获取元素定位的8种方法,需要的朋友可以参考下
    2024-02-02
  • python如何解决指定代码段超时程序卡死

    python如何解决指定代码段超时程序卡死

    这篇文章主要介绍了python如何解决指定代码段超时程序卡死,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11

最新评论