一篇很有营养的干货|看懂Python中的异步协程,这篇就够了

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

作者:崔庆才

链接:

https://mp.weixin.qq.com/s/jCc1jIHxU_p6bUlwijkwyQ

01.

什么是协程

协程,英文叫做 Coroutine,又称微线程,纤程,协程是一种用户态的轻量级线程。

协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。

我们可以使用协程来实现异步操作,比如在网络爬虫场景下,我们发出一个请求之后,需要等待一定的时间才能得到响应,但其实在这个等待过程中,程序可以干许多其他的事情,等到响应得到之后才切换回来继续处理,这样可以充分利用 CPU 和其他资源,这就是异步协程的优势。

02.

定义协程

首先我们来定义一个协程,体验一下它和普通进程在实现上的不同之处,代码如下:

import asyncio

async def execute(x):
    print('Number:', x)

coroutine = execute(1)
print('Coroutine:', coroutine)
print('After calling execute')

loop = asyncio.get_event_loop()
loop.run_until_complete(coroutine)
print('After calling loop')

运行结果:

Coroutine: <coroutine object execute at 0x1034cf830>
After calling execute
Number: 1
After calling loop

1).先import Python里面大名鼎鼎的asyncio这个异步包,然后才可以使用 async 和 await。我们接着 async 定义了一个 execute() 方法,方法接收一个数字参数,方法执行之后会打印这个数字。

2).随后我们直接调用了这个方法,然而这个方法并没有执行,而是返回了一个 coroutine 协程对象。

3).随后我们使用 get_event_loop() 方法创建了一个事件循环 loop,并调用了 loop 对象的 run_until_complete() 方法将协程注册到事件循环 loop 中,然后启动。最后我们才看到了 execute() 方法打印了输出结果。

4).可见,async 定义的方法就会变成一个无法直接执行的 coroutine 对象,必须将其注册到事件循环中才可以执行。

5).上文我们还提到了 task,它是对 coroutine 对象的进一步封装,它里面相比 coroutine 对象多了运行状态,比如 running、finished 等,我们可以用这些状态来获取协程对象的执行情况。

在上面的例子中,当我们将 coroutine 对象传递给 run_until_complete() 方法的时候,实际上它进行了一个操作就是将 coroutine 封装成了 task 对象,我们也可以显式地进行声明,如下所示:

import asyncio

async def execute(x):
    print('Number:', x)
    return x

coroutine = execute(1)
print('Coroutine:', coroutine)
print('After calling execute')

loop = asyncio.get_event_loop()
task = loop.create_task(coroutine)
print('Task:', task)
loop.run_until_complete(task)
print('Task:', task)
print('After calling loop')

运行结果:

Coroutine: <coroutine object execute at 0x10e0f7830>
After calling execute
Task: <Task pending coro=<execute() running at demo.py:4>>
Number: 1
Task: <Task finished coro=<execute() done, defined at demo.py:4> result=1>
After calling loop
  • 这里我们定义了 loop 对象之后,接着调用了它的 create_task() 方法将 coroutine 对象转化为了 task 对象

  • 随后我们打印输出一下,发现它是 pending 状态。接着我们将 task 对象添加到事件循环中得到执行,

  • 随后我们再打印输出一下 task 对象,发现它的状态就变成了 finished

  • 同时还可以看到其 result 变成了 1,也就是我们定义的 execute() 方法的返回结果。

另外定义 task 对象还有一种方式,就是直接通过 asyncio 的 ensure_future() 方法,返回结果也是 task 对象,这样的话我们就可以不借助于 loop 来定义,即使我们还没有声明 loop 也可以提前定义好 task 对象,写法如下:

import asyncio

async def execute(x):
    print('Number:', x)
    return x

coroutine = execute(1)
print('Coroutine:', coroutine)
print('After calling execute')

task = asyncio.ensure_future(coroutine)
print('Task:', task)
loop = asyncio.get_event_loop()
loop.run_until_complete(task)
print('Task:', task)
print('After calling loop')

运行结果:

Coroutine: <coroutine object execute at 0x10aa33830>
After calling execute
Task: <Task pending coro=<execute() running at demo.py:4>>
Number: 1
Task: <Task finished coro=<execute() done, defined at demo.py:4> result=1>
After calling loop

发现其效果都是一样的。

03.

绑定回调

另外我们也可以为某个 task 绑定一个回调方法,来看下面的例子:

import asyncio
import requests

async def request():
    url = 'https://www.baidu.com'
    status = requests.get(url)
    return status

def callback(task):
    print('Status:', task.result())

coroutine = request()
task = asyncio.ensure_future(coroutine)
task.add_done_callback(callback)
print('Task:', task)

loop = asyncio.get_event_loop()
loop.run_until_complete(task)
print('Task:', task)
  • 在这里我们定义了一个 request() 方法,请求了百度,返回状态码,但是这个方法里面我们没有任何 print() 语句。

  • 随后我们定义了一个 callback() 方法,这个方法接收一个参数,是 task 对象,然后调用 print() 方法打印了 task 对象的结果。

  • 这样我们就定义好了一个 coroutine 对象和一个回调方法,我们现在希望的效果是,当 coroutine 对象执行完毕之后,就去执行声明的 callback() 方法。

那么它们二者怎样关联起来呢?很简单,只需要调用 add_done_callback() 方法即可,我们将 callback() 方法传递给了封装好的 task 对象,这样当 task 执行完毕之后就可以调用 callback() 方法了。

同时 task 对象还会作为参数传递给 callback() 方法,调用 task 对象的 result() 方法就可以获取返回结果了。

运行结果:

Task: <Task pending coro=<request() running at demo.py:5> cb=[callback() at demo.py:11]>
Status: <Response [200]>
Task: <Task finished coro=<request() done, defined at demo.py:5> result=<Response [200]>>

实际上不用回调方法,直接在 task 运行完毕之后也可以直接调用 result() 方法获取结果,如下所示:

import asyncio
import requests

async def request():
    url = 'https://www.baidu.com'
    status = requests.get(url)
    return status

coroutine = request()
task = asyncio.ensure_future(coroutine)
print('Task:', task)

loop = asyncio.get_event_loop()
loop.run_until_complete(task)
print('Task:', task)
print('Task Result:', task.result())

运行结果是一样的:

Task: <Task pending coro=<request() running at demo.py:4>>
Task: <Task finished coro=<request() done, defined at demo.py:4> result=<Response [200]>>
Task Result: <Response [200]>


04.

多任务协程

上面的例子我们只执行了一次请求,如果我们想执行多次请求应该怎么办呢?我们可以定义一个 task 列表,然后使用 asyncio 的 wait() 方法即可执行,看下面的例子:

import asyncio
import requests

async def request():
    url = 'https://www.baidu.com'
    status = requests.get(url)
    return status

tasks = [asyncio.ensure_future(request()) for _ in range(5)]
print('Tasks:', tasks)

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

for task in tasks:
    print('Task Result:', task.result())

这里我们使用一个 for 循环创建了五个 task,组成了一个列表,然后把这个列表首先传递给了 asyncio 的 wait() 方法,然后再将其注册到时间循环中,就可以发起五个任务了。最后我们再将任务的运行结果输出出来,运行结果如下:

Tasks: [<Task pending coro=<request() running at demo.py:5>>, <Task pending coro=<request() running at demo.py:5>>, <Task pending coro=<request() running at demo.py:5>>, <Task pending coro=<request() running at demo.py:5>>, <Task pending coro=<request() running at demo.py:5>>]
Task Result: <Response [200]>
Task Result: <Response [200]>
Task Result: <Response [200]>
Task Result: <Response [200]>
Task Result: <Response [200]>

可以看到五个任务被顺次执行了,并得到了运行结果。

05.

一个实战爬虫例子,协程实现

前面说了这么一通,又是 async,又是 coroutine,又是 task,又是 callback,但似乎并没有看出协程的优势啊?反而写法上更加奇怪和麻烦了!

为了表现出协程的优势,最好的方法就是模拟一个需要等待一定时间才可以获取返回结果的网页,最好的方式是自己在本地模拟一个慢速服务器,这里我们选用 Flask,然后编写服务器代码如下:

from flask import Flask
import time

app = Flask(__name__)

@app.route('/')
def index():
    time.sleep(3)
    return 'Hello!'

if __name__ == '__main__':
    app.run(threaded=True)

这里我们定义了一个 Flask 服务,主入口是 index() 方法,方法里面先调用了 sleep() 方法休眠 3 秒,然后接着再返回结果,也就是说,每次请求这个接口至少要耗时 3 秒,这样我们就模拟了一个慢速的服务接口。

注意这里服务启动的时候,run() 方法加了一个参数 threaded,这表明 Flask 启动了多线程模式,不然默认是只有一个线程的。

如果不开启多线程模式,同一时刻遇到多个请求的时候,只能顺次处理,这样即使我们使用协程异步请求了这个服务,也只能一个一个排队等待,瓶颈就会出现在服务端。所以,多线程模式是有必要打开的。

启动之后,Flask 应该默认会在 127.0.0.1:5000 上运行,运行之后控制台输出结果如下:

 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

接下来我们再重新使用上面的方法请求一遍:

import asyncio
import requests
import time

start = time.time()

async def request():
    url = 'http://127.0.0.1:5000'
    print('Waiting for', url)
    response = requests.get(url)
    print('Get response from', url, 'Result:', response.text)

tasks = [asyncio.ensure_future(request()) for _ in range(5)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

end = time.time()
print('Cost time:', end - start)

在这里我们还是创建了五个 task,然后将 task 列表传给 wait() 方法并注册到时间循环中执行。

运行结果如下:

Waiting for http://127.0.0.1:5000
Get response from http://127.0.0.1:5000 Result: Hello!
Waiting for http://127.0.0.1:5000
Get response from http://127.0.0.1:5000 Result: Hello!
Waiting for http://127.0.0.1:5000
Get response from http://127.0.0.1:5000 Result: Hello!
Waiting for http://127.0.0.1:5000
Get response from http://127.0.0.1:5000 Result: Hello!
Waiting for http://127.0.0.1:5000
Get response from http://127.0.0.1:5000 Result: Hello!
Cost time: 15.049368143081665

可以发现和正常的请求并没有什么两样,依然还是顺次执行的,耗时 15 秒,平均一个请求耗时 3 秒,说好的异步处理呢?

其实,要实现异步处理,我们得先要有挂起的操作,当一个任务需要等待 IO 结果的时候,可以挂起当前任务,转而去执行其他任务,这样我们才能充分利用好资源,上面方法都是一本正经的串行走下来,连个挂起都没有,怎么可能实现异步?想太多了。

要实现异步,接下来我们再了解一下 await 的用法,使用 await 可以将耗时等待的操作挂起,让出控制权。当协程执行的时候遇到 await,时间循环就会将本协程挂起,转而去执行别的协程,直到其他的协程挂起或执行完毕。

所以,我们可能会将代码中的 request() 方法改成如下的样子:

async def request():
    url = 'http://127.0.0.1:5000'
    print('Waiting for', url)
    response = await requests.get(url)
    print('Get response from', url, 'Result:', response.text)

仅仅是在 requests 前面加了一个 await,然而执行以下代码,会得到如下报错:

Waiting for http://127.0.0.1:5000
Waiting for http://127.0.0.1:5000
Waiting for http://127.0.0.1:5000
Waiting for http://127.0.0.1:5000
Waiting for http://127.0.0.1:5000
Cost time: 15.048935890197754
Task exception was never retrieved
future: <Task finished coro=<request() done, defined at demo.py:7> exception=TypeError("object Response can't be used in 'await' expression",)>
Traceback (most recent call last):
  File "demo.py", line 10, in request
    status = await requests.get(url)
TypeError: object Response can't be used in 'await' expression

这次它遇到 await 方法确实挂起了,也等待了,但是最后却报了这么个错,这个错误的意思是 requests 返回的 Response 对象不能和 await 一起使用,为什么呢?因为根据官方文档说明,await 后面的对象必须是如下格式之一:

  • A native coroutine object returned from a native coroutine function,一个原生 coroutine 对象。

  • A generator-based coroutine object returned from a function decorated with types.coroutine(),一个由 types.coroutine() 修饰的生成器,这个生成器可以返回 coroutine 对象。

  • An object with an await__ method returning an iterator,一个包含 __await 方法的对象返回的一个迭代器。

reqeusts 返回的 Response 不符合上面任一条件,因此就会报上面的错误了。那么有的小伙伴就发现了,既然 await 后面可以跟一个 coroutine 对象,那么我用 async 把请求的方法改成 coroutine 对象不就可以了吗?所以就改写成如下的样子:

import asyncio
import requests
import time

start = time.time()

async def get(url):
    return requests.get(url)

async def request():
    url = 'http://127.0.0.1:5000'
    print('Waiting for', url)
    response = await get(url)
    print('Get response from', url, 'Result:', response.text)

tasks = [asyncio.ensure_future(request()) for _ in range(5)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

end = time.time()
print('Cost time:', end - start)

这里我们将请求页面的方法独立出来,并用 async 修饰,这样就得到了一个 coroutine 对象,我们运行一下看看:

Waiting for http://127.0.0.1:5000
Get response from http://127.0.0.1:5000 Result: Hello!
Waiting for http://127.0.0.1:5000
Get response from http://127.0.0.1:5000 Result: Hello!
Waiting for http://127.0.0.1:5000
Get response from http://127.0.0.1:5000 Result: Hello!
Waiting for http://127.0.0.1:5000
Get response from http://127.0.0.1:5000 Result: Hello!
Waiting for http://127.0.0.1:5000
Get response from http://127.0.0.1:5000 Result: Hello!
Cost time: 15.134317874908447

还是不行,它还不是异步执行,也就是说我们仅仅将涉及 IO 操作的代码封装到 async 修饰的方法里面是不可行的!我们必须要使用支持异步操作的请求方式才可以实现真正的异步,所以这里就需要 aiohttp 派上用场了。

06.

使用 aiohttp

aiohttp 是一个支持异步请求的库,利用它和 asyncio 配合我们可以非常方便地实现异步请求操作。我们将 aiohttp 用上来,将代码改成如下样子:

import asyncio
import aiohttp
import time

start = time.time()

async def get(url):
    session = aiohttp.ClientSession()
    response = await session.get(url)
    result = await response.text()
    session.close()
    return result

async def request():
    url = 'http://127.0.0.1:5000'
    print('Waiting for', url)
    result = await get(url)
    print('Get response from', url, 'Result:', result)

tasks = [asyncio.ensure_future(request()) for _ in range(5)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

end = time.time()
print('Cost time:', end - start)

在这里我们将请求库由 requests 改成了 aiohttp,通过 aiohttp 的 ClientSession 类的 get() 方法进行请求,结果如下:

Waiting for http://127.0.0.1:5000
Waiting for http://127.0.0.1:5000
Waiting for http://127.0.0.1:5000
Waiting for http://127.0.0.1:5000
Waiting for http://127.0.0.1:5000
Get response from http://127.0.0.1:5000 Result: Hello!
Get response from http://127.0.0.1:5000 Result: Hello!
Get response from http://127.0.0.1:5000 Result: Hello!
Get response from http://127.0.0.1:5000 Result: Hello!
Get response from http://127.0.0.1:5000 Result: Hello!
Cost time: 3.0199508666992188

成功了!我们发现这次请求的耗时由 15 秒变成了 3 秒,耗时直接变成了原来的 1/5。

近期十大热门:

每个程序员都是从菜鸟开始成长起来的,没有人一开始就是程序员高手。菜鸟爱编程,专注于分享趣味的编程技巧,不限于Java, Python ,Go, Javascript等语言,让菜鸟爱上编程,进阶成为高手。

菜鸟编程大本营

长按2秒,输入:【书单】
点这里,进菜鸟学PythonB站大本营
flask多进程多线程配置 flask.Flask.run接受**options转发给它的其他关键字参数()werkzeug.serving.run_simple-其中两个参数是threaded(布尔值)和processes(您可以将其设置为大于1的数字以使werkzeug产生多个进程来处理请求)。 threaded默认True版本自Flask 1.0起,因此对于最新版本的Flask,默认情况下默认开发服务器将能同时为多个客户端提供服务。对于较旧版本的Flask,您可以显式传递threaded=True以启用此行为。 例如,您可以 阅读详情

相关推荐

python 异步协程最简单教学

python异步编程

weixin_45621200的博客 1236

[python] ThreadPoolExecutor线程池

初识Python中已经有了threading模块,为什么还需要线程池呢,线程池又是什么东西呢?在介绍线程同步的信号量机制的时候,举得例子是爬虫的例子,需要控制同时爬取的线程数,例子中创建了20个线程,而同时只允许3个线程在运行,但是20个线程都需要创建和销毁,线程的创建是需要消耗系统资源的,有没有更好的方案呢?其实只需要三个线程就行了,每个线程各分配一个任务,剩下的任务排队等待,当某个线程完成了任...

wudiazu的博客 1万+

菜鸟初学python入门进阶第十一节:面向对象,协程异步io

python协程异步io编程1.并发、并行、同步、异步、阻塞、非阻塞2.C10K问题和io多路复用 1.并发、并行、同步、异步、阻塞、非阻塞 并发:一个时间段内,有几个程序在同一个cpu上运行,但任意时刻只有一个程序在cpu上运行 并行:任意时刻点上,有多个程序同时运行在多个cpu上 同步:指代码调用io操作时,必须等待io操作完成才返回的调用方式 异步:指代码调用io操作时,不必等待io操作完成才返回的调用方式 多线程是典型异步操作 io操作可以看成是消息通信 阻塞:调用函数时线程被挂起 非阻塞:调用

lafea的博客 540

python的celery的面试_面试必问的celery,你了解多少?

celery是什么,有什么用?对于celery,各种文档解释一堆,可以自己看下,根据日常互动,公众号用户小白居多,官方用到的很多名词可能你理解起来不是那么容易,我这里就不照本宣科了,就以我这边的理解简单以下方图示解释下,如果有误,欢迎指正:首先理解一个概念:阻塞理解阻塞,先从耗时操作讲起,常见的场景比如用户输入、等待(sleep)这些都属于,具体到实际项目中比如说发邮件、发短信、机器/深度学习训...

weixin_39889544的博客 966

15_Flask之分析线程和协程

文章目录01 思考:每个请求之间的关系02 threading.local03 通过字典自定义threading.local04 通过setattr和getattr实现自定义threthreading.local05 每个对象有自己的存储空间(字典)06 如果是你会如何设计flask的请求并发? 01 思考:每个请求之间的关系 我们每一个请求进来的时候都开一个进程肯定不合理,那么如果每一个请求进来都是串行的,那么根本实现不了并发,所以我们假定每一个请求进来使用的是线程。 那么线程中数据互相不隔离,存在修改数

coderge's CSDN Blog. 622

flask异步协程提高并发gevent

本身app.run()自带了相关线程进程相关属性,但是效果不是很好,可以结合协程库gevent提高并发 1、添加相关库 ** from gevent.pywsgi import WSGIServer from gevent import monkey monkey.patch_all()** 2、修改运行 if name == ‘main’: # app.run(debug=True) http_......

weixin_42357472的博客 3683

python协程 应用场景_一篇很有营养干货|看懂Python中的异步协程,这...

原标题:一篇很有营养干货|看懂Python中的异步协程,这了作者:崔庆才链接:https://mp.weixin.qq.com/s/jCc1jIHxU_p6bUlwijkwyQ本文内容非常丰富,对小白深入了解Python 协程非常有帮助,请大家耐心看完01.什么是协程协程,英文叫做 Coroutine,又称微线程,纤程,协程是一种用户态的轻量级线程。协程拥有自己的寄存器上下文和栈。协程调度...

weixin_39772352的博客 1187

python协程实时输出_一篇很有营养干货 | 看懂Python中的异步协程,这了!...

原标题:一篇很有营养干货 | 看懂Python中的异步协程,这了!源 /进击的Coder文 /崔庆才01.什么是协程协程,英文叫做 Coroutine,又称微线程,纤程,协程是一种用户态的轻量级线程。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。我们可以使用协程来实现异步操作,比如在网络爬虫场景下,我们发出...

weixin_39676930的博客 312

Python纯内存事件总线:零依赖Pub/Sub实现与生产实践

事件总线是分布式系统解耦的核心机制,其本质是通过异步消息传递实现模块间松耦合协作。基于Python标准库的内存型事件总线,依托queue.Queue的线程安全特性与threading原语,无需外部中间件即可构建低延迟、高可控的内部通信骨架。相比Redis或Kafka等重量级方案,它在单进程多线程场景下具备零序列化开销、强类型保真、易调试和快速演进等技术优势,特别适用于MVP验证、配置热更新、埋点分发及微服务内部解耦等轻量级事件驱动场景。

weixin_33721344的博客 381

AI slop与内容治理:理性构建AI生成内容检测服务

随着大模型技术普及,AI生成内容已覆盖日常写作、社区问答和资讯分发,批量低质内容催生了“AI slop”现象。理解其产生机制与识别原理,成为当前内容平台治理的关键。从自然语言处理与机器学习角度看,AI生成内容检测融合了统计特征、文本分类和水印等多项技术,普遍面临误报率与召回率的权衡。作为内容审核的辅助工具,AI检测可以定位高风险内容并分层处置,却不应被当作唯一结论。在社区治理、创作服务平台和内容分发场景中,引入检测服务并结合人工复核与申诉闭环,有助于平衡内容生态与创作者体验。本文基于工程实践,演示从零搭建一

weixin_34357436的博客 390

python异步协程爬虫报错:【TypeError: object int can‘t be used in ‘await‘ expression】探讨

这个例子中,my_function()是一个异步函数,它会等待1秒钟后再执行后续的操作。await asyncio.sleep(1)是等待1秒钟的语句,它返回的是一个协程对象,可以用await来等待它执行完毕。要解决这个问题,需要确保await的参数是一个异步函数的返回值。如果我们只是想等待一个时间段后再执行下一个操作,可以使用asyncio.sleep()函数作为协程对象来等待一定的时间。这个错误的原因可能是在async函数中使用了一个整数类型的变量作为await的参数。好让人郁闷( ˇˍˇ )

teotv的博客 7058

最新Python异步编程详解

我们都知道对于I/O相关的程序来说,异步编程可以大幅度的提高系统的吞吐量,因为在某个I/O操作的读写过程中,系统可以先去处理其它的操作(通常是其它的I/O操作),那么Python中是如何实现异步编程的呢? 简单的回答是Python通过协程(coroutine)来实现异步编程。那究竟啥是协程呢?这将是一个很长的故事。 故事要从yield开始说起(已经熟悉yield的读者可以跳过...

dianyin7770的博客 437

python 异步编程之协程

python 协程原理和使用

qq_43745578的博客 1732

Python异步协程

Python asyncio 异步协程百万并发 协程coroutine) 本质就是一个函数 事件循环——(event_loop) 协程函数,不是像普通函数那样直接调用运行的,必须添加到事件循环中,然后由事件循环去运行,单独运行协程函数是不会有结果的,看一个简单的例子: import time import asyncio async def say_after_time(delay,what): await asyncio.sleep(delay) print(what

by_zhou 2184

Python异步编程之协程

官方文档事件循环 — Python 3.12.0 文档1、异步编程是一种并发编程的模式,在不同任务之间进行调度切换执行,减少CPU的空闲时间一达到减小整个程序的执行时间。2、与多线程和多进程并发编程模式相比,异步编辑就是协程并发执行的处理,即在同一个线程下不同任务之间的调度,所以异步编程无法充分利用多核CPU的优势,适用于IO阻塞性任务。3、异步编程的可应用于协程控制执行网络IO和IPC控制子进程、通过队列实现分布式任务、同步并发代码。

lIujunXHU的博客 2098

Python异步协程的使用方法介绍

1前言: 在执行一些 IO 密集型任务的时候,程序常常会因为等待 IO 而阻塞。比如在网络爬虫中,如果我们使用 requests 库来进行请求的话,如果网站响应速度过慢,程序一直在等待网站响应,最后导致其爬取效率是非常非常低的。 为了解决这类问题,本文就来探讨一下 Python异步协程来加速的方法,此种方法对于 IO 密集型任务非常有效。如将其应用到网络爬虫中,爬取效率甚至可以成百倍地提升。 注:本文协程使用 async/await 来实现,需要 Python 3.5 及以上版本1: 2基本了解

aa804738534的博客 2017

Python协程异步IO(asyncio)详解

协程不是系统级线程,很多时候协程被称为“轻量级线程”、“微线程”、“纤程(fiber)”等。简单来说可以认为协程是线程里不同的函数,这些函数之间可以相互快速切换。协程和用户态线程非常接近,用户态线程之间的切换不需要陷入内核,但部分操作系统中用户态线程的切换需要内核态线程的辅助。协程编程语言(或者 lib)提供的特性(协程之间的切换方式与过程可以由编程人员确定),是用户态操作。协程适用于 IO 密集型的任务。

创作不易,请多支持,将为本站提供更多「有价值的文章」。 1万+

TypeError: object list can‘t be used in ‘await‘ expression

object list can't be used in 'await' expression 异常解决

SooKie_p的博客 3612
上一篇: Java收入不再最低,Python被TypeScript击败,2020全球开发者调查报告出炉
下一篇: Python这么慢,为啥大公司还在用?
菜鸟学Python
博客等级 码龄9年 7562粉丝 571原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值