【python技能】掌握这3点,轻松搞定python协程

自从python3开始普及之后,那么协程就成为了很多应用的性能首选,于是很多从python2转过来的小伙伴们就纷纷的投入它的怀抱。不管是做web开发还是爬虫开发,要想做到更高的并发和更好的系统资源的利用都离不开它。

在python3.7之前,学习这个玩意还是有些伤脑筋的,为什么呢?因为它的语法对于很多人来讲不是很友好,而且用到的方法太多了,导致很多人学的时候都是晕乎乎的完全不明所以。因此很多的小伙伴也就退而求其次的选择用多线程解决,毕竟多线程写起来还是那么的熟练和简单嘛。

掌握Python3的协程只要记住以下几个重要概念和注意事项就OK。非常好入门,我们这里用的是python3.8,如果是你,那么请使用python3.7以上的版本。

  • 协程函数
  • 可等待对象
  • 任务

什么是协程?

在python里面,协程的概念很简单,python的协程就是用async def定义的函数,这个函数也叫协程函数。

看起来大概是这样的:

async def main():
     print('hello')
     await asyncio.sleep(1)
     print('world')

那么如何运行一个协程函数呢?记住这三点就可以了:

  • 使用await关键字,就好比上面的例子那样,在await右边放上你的协程函数
  • 使用asyncio.create_task函数并发的执行,这个后面会讲
  • 使用asyncio.run函数执行,这个主要就是用来运行主入口协程函数的

上面的例子我们就可以这么执行:

asyncio.run(main())

我们还可以看到,这个函数里面还有一个新奇的关键字await,这个是干嘛的呢?

从字面上理解就是异步的等待,它会等待它右边的函数执行完成,但是这个它是异步的。什么意思呢?也就是一旦遇到这个await那么这个函数就暂时在这里暂停了,然后程序可以去执行其他的一些操作,当它右边的函数执行完成之后,才会继续往下执行。

能放在await右边的对象叫做「可等待对象」

可等待对象

python里面的可等待对象说的是可以放在await 关键字右边的对象(python里面一切皆对象)。可等待对象有哪些?

  • 协程函数,前面说到的
  • 任务(Task)后面会讲
  • Future对象,这个大部分情况下用不到,不用理会

那么关于await除了知道只有上面的三种对象可以进行await之外,就是要记住,这个await只能出现在协程函数里面,别的地方是不能出现的哦,普通函数里面也没有的。所以这样就知道如何使用它啦。

import asyncio
async def nested():
return 42
async def main():
# 像这样子是不会被执行的
nested()
# 可以通过await来执行它
print(await nested()) # 打印输出 "42".
asyncio.run(main())

最后来看看这个任务对象

任务对象

协程函数本身是不会进行并发的,要想并发的执行协程函数,那么就得通过创建任务的方式来进行,所以这个任务对象的主要目的就是让协程函数可以并发的执行。

「如何创建一个任务呢?」使用asyncio.create_task函数就可以创建一个任务啦。只需要传入要被执行的协程函数就可以并发的进行运行了。

import asyncio
async def say_after(delay, what):
await asyncio.sleep(delay)
print(what)

async def main():
task1 = asyncio.create_task(
say_after(1, 'hello'))
task2 = asyncio.create_task(
say_after(2, 'world'))
print(f"started at {time.strftime('%X')}")


# 使用await等待任务结束
await task1
await task2
print(f"finished at {time.strftime('%X')}")asyncio.run(main())

任务有什么特点呢?

任务创建函数只是将协程函数并发的执行,所以它的参数里面只能传入协程函数,而不能是其它东西。

当然,要实现并发的执行协程函数还有另外的一个方法

asyncio.gather函数,它可以并发执行N个可等待对象,注意是可等待对象。

import asyncio

async def factorial(name, number):
f = 1
for i in range(2, number + 1):
print(f"Task {name}: Compute factorial({i})...")
await asyncio.sleep(1)
f *= i
print(f"Task {name}: factorial({number}) = {f}")



async def main():
# 这里会并发的执行三个协程函数
await asyncio.gather(
factorial("A", 2),
factorial("B", 3),
factorial("C", 4),
)
asyncio.run(main())

但是这个本质上也会转换为任务对象然后再执行。

最后还要说一点就是这个asyncio.run()函数,这个函数正常情况下,在一个python程序里面只调用一次,如果需要调用多次的话,只能是等待上一个函数执行完成之后再调用,否则就会抛出RuntimeError的错误。

总结

基本上写python的协程脚本,只需要记住上面提到的几点就OK,这里总结一下。

  1. 协程函数是由async def来进行声明和定义的,想要执行协程函数必须使用await或创建任务或者是通过asyncio.run方法执行
  2. await 是用于等待可等待对象的完成,可等待对象有三种,协程函数、Task任务和Future对象,await只能出现在协程函数里面。
  3. 协程函数本身不会并发执行,它必须的通过创建任务来并发执行,所以任务的主要目的就是并发的执行协程函数。
  4. 任务只能是在协程函数里面创建和运行哦,普通函数里面创建任务是会失败的。
  5. asyncio.run函数一般在一个脚本里面只建议出现一次,多次出现的话得有执行顺序,一般不建议多次出现。它的目的就是用来执行程序主入口协程函数。

今天就到这里吧。其实很多东西没你想的那么难哈!

关注我,学习更多的SEO相关技术

[python技能]掌握这3点,轻松搞定python协程

THE END
分享
二维码
海报
【python技能】掌握这3点,轻松搞定python协程
自从python3开始普及之后,那么协程就成为了很多应用的性能首选,于是很多从python2转过来的小伙伴们就纷纷的投入它的怀抱。不管是做web开发还是爬虫开发,要……
<<上一篇
下一篇>>