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

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

作者:崔庆才

链接:

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站大本营
python异步爬虫的使用方法 而asyncio则是Python对异步编程的支持库,它提供了非常好的异步编程支持。Python对异步编程的支持非常友好,因为Python提供了非常实用的库——asyncio来实现异步编程。如果需要异步爬取多个网页,而不是单个网页,就需要使用asyncio库的生产者-消费者模式。生产者负责生成任务,并将任务推送到队列中,而消费者负责从队列中取出任务,并执行这些任务。aiohttp支持async/await语法,我们需要定义异步函数,使用async关键字,紧随其后的是函数的名称和参数。 阅读详情

相关推荐

Docker新手必看:解决‘Unable to find image’错误的完整指南

本文针对Docker新手常见的‘Unable to find image’错误,提供了完整的排查与解决指南。文章深入剖析了权限不足、网络连接失败、Docker服务未运行等核心原因,并给出了将用户加入docker组、配置镜像加速器等实用解决方案,帮助读者彻底理解并解决镜像拉取问题。

weixin_29230901的博客 244

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

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

lafea的博客 544

告别第三方工具!用Windows自带蓝牙玩转BLE设备调试(保姆级图文教程)

本文详细介绍了如何利用Windows自带的蓝牙功能进行BLE设备调试,无需第三方工具。从硬件准备、系统配置到实战操作,提供保姆级图文教程,帮助开发者高效完成设备发现、数据交互等全流程调试工作。特别适合物联网开发者和智能硬件爱好者。

o5p6q的博客 727

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

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

weixin_39889544的博客 972

Unity3D 2022版如何一键安装Newtonsoft.Json?最新Package Manager教程

本文详细介绍了在Unity3D 2022及以上版本中,如何通过Package Manager一键安装和配置Newtonsoft.Json(Json.NET)。教程涵盖了从打开Package Manager、搜索并安装正确包源,到验证安装和基础使用的完整流程,旨在帮助开发者以现代化、可靠的方式集成这一强大的JSON处理框架,提升开发效率并规避手动导入的常见问题。

lg888的博客 921

网课、网页视频倍速播放简单脚本

一个简单的网页视频倍速脚本

huazn612的博客 1万+

15_Flask之分析线程和协程

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

coderge's 优快云 Blog. 627

脑机接口(BCI)从原理到开发实战 01|意念控制真的来了?一文看懂脑机接口的技术革命

类型定义典型应用主动式用户主动产生特定思维模式来控制设备运动想象(想象左手/右手移动)反应式用户被动接受外部刺激,系统检测大脑反应P300拼写器、SSVEP(稳态视觉诱发电位)被动式系统监测用户自发脑状态,不要求主动控制疲劳监测、情绪识别、注意力评估本系列后续文章将重点围绕主动式(运动想象)和反应式(P300/SSVEP)展开实战。脑机接口,这个曾经只存在于科幻中的概念,正在政策、资本、技术的三重驱动下,加速从实验室走向产业落地。2026年,注定是脑机接口发展史上浓墨重彩的一年。

小明的博客 1431

[python] ThreadPoolExecutor线程池

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

wudiazu的博客 1万+

芒果YOLOv8改进165:损失函数angleLoss:即插即用 | 独家首发原创新颖|公开数据集DOTA高效无损涨点0.5% | 旋转检测

YOLOv8改进:旋转检测Loss损失函数angleLoss:即插即用 | 独家首发原创新颖|公开数据集DOTA高效无损涨点0.5%

包括YOLOv5、YOLOv7、YOLOv8等模型改进 1150

Python爬虫实战:爬取500+网易云热门歌单,我摸清了全网最火的音乐规律

曲风:流行是主流,“情绪价值”比单纯曲风更重要;歌名:感性、场景化的歌名,更受用户偏爱。这次实战让我明白,Python不是冰冷的代码,而是能帮我们看清生活中隐藏规律的工具。从每天刷的歌单里,用爬虫和数据分析挖出用户的真实偏好,不仅满足了好奇心,还实实在在练会了技能。新手朋友可以从这个项目入手,既练习了爬虫基础,又学会了数据分析的核心逻辑,还能结合自己的音乐兴趣理解数据的意义。现在打开PyCharm,跟着代码跑一遍,你也能从网易云的热门歌单里,挖出属于自己的“音乐规律”!

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1889

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的博客 3701

【WRF数据准备】生成 LCZ 对应的FRC_URB2D

WRF 静态地理数据准备

WW、forever的博客 409

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

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

weixin_39772352的博客 1187

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

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

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

weixin_39676930的博客 315

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

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

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

weixin_33721344的博客 385

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

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

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

weixin_34357436的博客 394

python爬虫-异步爬虫

对异步爬虫从概念学习,到进阶,再到实例

dayexiaofan的博客 2718

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的博客 7073

最新Python异步编程详解

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

dianyin7770的博客 439

Python爬虫之异步爬虫

协程的基本原理、aiohttp的使用、aiohttp异步爬取实战。import asyncio # 引入asyncio包,这样才能使用async和await关键字。async def execute(x): # 使用async定义了一个execute方法,该方法接受一个数字参数x,执行之后会打印这个数字。coroutine = execute(1) # 调用这execute方法,然而没有被执行,而是返回了一个coroutine协程对象。

恐龙让Lee的博客 1883

python 异步编程之协程

python 协程原理和使用

qq_43745578的博客 1735

python异步爬虫的实现过程

在日常爬虫中我们会涉及到同步与异步问题,一般异步编程可以大幅度的提高系统的吞吐量,提高单位时间内发出的请求数目。之前的文章分享了些同步的知识,就是对aurl发起请求,等待响应。2、线程池、进程池(适当的使用):好处:可以降低系统对进程或者线程创建和销毁的一个频率,从而很好的降低系统的开销。大量的时间消耗在等待上,如果能近似的同时对多个网址发起请求,等待响应,速度回快很多倍。其实所谓的同时也是有先后顺序的,所以叫异步。好处:可以为相关阻塞的操作单独开启线程,阻塞操作就可以异步执行。异步爬虫的方式有以下2种。

Z_suger7的博客 797

python爬虫进阶篇(异步)

异步学习完前面的基础知识后,我们会发现这些爬虫的效率实在是太低了。那么我们需要学习一些新的爬虫方式来进行信息的获取。异步使用python3.7后的版本中的异步进行爬取,多线程虽然快,但是异步才是爬虫真爱。基本概念讲解1.什么是异步?异步是指在程序执行过程中,当遇到耗时的操作时,不会等待这个操作完成才继续执行后面的代码,而是先去执行其他的操作,等到耗时的操作完成后再处理它的结果。这种方式能够提高程序的并发性和响应性。

screamn的博客 2274

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

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值