python 异步编程 区分并发,并行,同步,异步,进程,线程,协程

1 js异步编程比较好理解。
所以这篇文章使用js_echarts+python_PyQt5制作看板时使用js做异步处理。(​​https://blog.csdn.net/lildkdkdkjf/article/details/106571356​​)
async/await 在 JavaScript 中的 Promise 类中很常用。promise主要是用来解决回调地狱的问题。Promise是异步编程的一种解决方案,它的构造函数是同步执行的,then 方法是异步执行的,所以Promise创建后里面的函数会立即执行,构造函数中的resolve和reject只有第一次执行有效,,也就是说Promise状态一旦改变就不能再变。(​​https://blog.csdn.net/qq_53669554/article/details/131598219)​​

2 Python 异步编程入门

Python 并不支持专门的异步编程语法,因为不需要。
有了多线程(threading)和多进程(multiprocessing),就没必要一定支持异步了。如果一个线程(或进程)阻塞,新建其他线程(或进程)就可以了,程序不会卡死。但是,多线程有"线程竞争"的问题,处理起来很复杂,还涉及加锁。对于简单的异步任务来说(比如与网页互动),写起来很麻烦。(​​https://ruanyifeng.com/blog/2019/11/python-asyncio.html​​)
asyncio 模块最大特点就是,只存在一个线程,跟 JavaScript 一样。

下面介绍 asyncio 模块最主要的几个API。注意,必须使用 Python 3.7 或更高版本,早期的语法已经变了。

最后是一个异步编程的真实例子:操作无头浏览器。异步编程对代码的简化,在这个例子体现得淋漓尽致。

无头浏览器,即 Headless Browser,是一种没有界面的浏览器。它拥有完整的浏览器内核,包括 JavaScript 解析引擎、渲染引擎等。与普通浏览器最大的不同是,无头浏览器执行过程中看不到运行的界面,但是我们依然可以用 GUI 测试框架的截图功能截取它执行中的页面。在这里强调一下,好多文章说无头浏览器不做渲染,其实这个说法是不准确的,如果无头浏览器不做渲染,那么怎么进行截图呢?可能有人又要说,如果无头浏览器都做渲染的话,那速度又怎么保障呢?个人观点,应该是在需要截屏的时候才进行页面元素的渲染!​​https://blog.csdn.net/liwenxiang629/article/details/127964900​​

3 同步/异步
python由于GIL(全局锁)的存在,不能发挥多核的优势,其性能一直饱受诟病。然而在IO密集型的网络编程里,异步处理比同步处理能提升成百上千倍的效率,弥补了python性能方面的短板,如最新的微服务框架japronto,resquests per second可达百万级。
python还有一个优势是库(第三方库)极为丰富,运用十分方便。asyncio是python3.4版本引入到标准库。(
理清楚同步/异步的概念:

·同步是指完成事务的逻辑,先执行第一个事务,如果阻塞了,会一直等待,直到这个事务完成,再执行第二个事务,顺序执行。。。

·异步是和同步相对的,异步是指在处理调用这个事务的之后,不会等待这个事务的处理结果,直接处理第二个事务去了,通过状态、通知、回调来通知调用者处理结果。

async def hello():
    await asyncio.sleep(1)
    print('Hello World:%s' % time.time())这段代码定义了一个异步函数​​hello()​​。

下面是对代码中每个关键部分的解释:
• ​​async def​​: 这是Python中定义异步函数的语法。异步函数可以在执行过程中暂停并等待其他任务完成。
• ​​hello()​​: 这是函数的名称,您可以根据需要自定义函数名称。
• ​​await asyncio.sleep(1)​​​: ​​await​​​关键字用于暂停函数的执行,直到​​asyncio.sleep(1)​​​完成。​​asyncio.sleep(1)​​是一个异步函数,它会暂停执行1秒钟。
• ​​print(‘Hello World:%s’ % time.time())​​​: 这行代码会在控制台打印出​​Hello World:​​​和当前时间的字符串。​​%s​​​是一个占位符,用于将​​time.time()​​的结果插入到字符串中。
这段代码使用了异步编程的特性,通过​​await​​​关键字来等待异步任务完成。在这个例子中,​​await asyncio.sleep(1)​​​会暂停函数的执行1秒钟,然后继续执行后面的代码。最后,​​print​​​语句会将字符串​​Hello World:​​和当前时间打印到控制台上。
 如果需要并发http请求怎么办呢,通常是用requests,但requests是同步的库,如果想异步的话需要引入aiohttp。这里引入一个类,from aiohttp import ClientSession,首先要建立一个session对象,然后用session对象去打开网页。session可以进行多项操作,比如post, get, put, head等。

4 并发,并行,同步,异步,进程,线程,协程
使用 async 和 await 协程进行并发编程。python 一直在进行并发编程的优化, 比较熟知的是使用 thread 模块多线程和 multiprocessing 多进程,后来慢慢引入基于 yield 关键字的协程。 而近几个版本,python 对于协程的写法进行了大幅的优化,很多之前的协程写法不被官方推荐了。如果你之前了解过 python 协程,你应该看看最新的用法。 python 3.7 里面的基础协程用法,现在这种用法已经基本稳定,不太建议使用之前的语法了。
(​​https://www.cnblogs.com/heniu/p/12740400.html​​)
并发指的是 一个 CPU 同时处理多个程序,但是在同一时间点只会处理其中一个。并发的核心是:程序切换。
但是因为程序切换的速度非常快,1 秒钟内可以完全很多次程序切换,肉眼无法感知。
并行指的是多个 CPU 同时处理多个程序,同一时间点可以处理多个。
同步:执行 IO 操作时,必须等待执行完成才得到返回结果。异步:执行 IO 操作时,不必等待执行就能得到返回结果。

多进程通常利用的是多核 CPU 的优势,同时执行多个计算任务。每个进程有自己独立的内存管理,所以不同进程之间要进行数据通信比较麻烦。多线程是在一个 cpu 上创建多个子任务,当某一个子任务休息的时候其他任务接着执行。多线程的控制是由 python 自己控制的。 子线程之间的内存是共享的,并不需要额外的数据通信机制。但是线程存在数据同步问题,所以要有锁机制。协程的实现是在一个线程内实现的,相当于流水线作业。由于线程切换的消耗比较大,所以对于并发编程,可以优先使用协程。

import asyncio
import time

async def visit_url(url, response_time):
    """访问 url"""
    await asyncio.sleep(response_time)
    return f"访问{url}, 已得到返回结果"

start_time = time.perf_counter()
task = visit_url('http://wangzhen.com', 2)
asyncio.run(task)
print(f"消耗时间:{time.perf_counter() - start_time}")

• 1, 在普通的函数前面加 async 关键字;
• 2,await 表示在这个地方等待子函数执行完成,再往下执行。(在并发操作中,把程序控制权教给主程序,让他分配其他协程执行。) await 只能在带有 async 关键字的函数中运行。
• 3, asynico.run() 运行程序
• 4, 这个程序消• 耗时间 2s 左右。
增加协程
• 再添加一个任务:

task2 = visit_url('http://another.com', 3)
asynicio.run(task2)

• 要想使用并发编程形式,需要把上面的代码改一下。asyncio.gather 会创建 2 个子任务,当出现 await 的时候,程序会在这 2 个子任务之间进行调度。
• 创建子任务除了可以用 gather 方法之外,还可以使用 asyncio.create_task 进行创建。

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值