Python使用Asyncio进行web编程方法详解

目录
  • 前言
  • 什么是同步编程
  • 什么是异步编程
  • ayncio 版 Hello 程序
  • 如何使用 asyncio
  • 总结

前言

许多 Web 应用依赖大量的 I/O (输入/输出) 操作,比如从网站上下载图片、视频等内容;进行网络聊天或者针对后台数据库进行多次查询。数据库查询可能会耗费大量时间,尤其是在该数据库处于高负载或查询很复杂的情况下。 Web 服务器可能需要同时处理数百或数千个请求。

I/O 是指计算机的输入和输出设备,例如键盘、硬盘驱动器,以及最常见的网卡。这些操作等待用户输入或从基于 Web 的 API 检索内容。

Asynchronous IO (async IO) 是一种异步编程设计,并在 Python 3.4 的 asyncio 模块中得到了支持,作为在多线程和多进程之外处理这些高并发工作负载的另一种方法,可以显着提高使用 I/O 操作的应用程序的性能和资源利用率。

什么是同步编程

同步编程,通常来说,大多数编程语言都是子例程调用模型:按照顺序运行代码。在此模型中,下一行代码在前一行代码完成后立即运行,并且一次只完成一个模块。

该模型适用于大部分应用程序。但是,也存在明显的缺点,如果一行代码特别慢怎么办?

在这种情况下,速度慢的代码将导致所有其他代码都将被卡住,直到该行完成。最差的情况下可能导致整个应用程序卡死。可能大多数人在某些软件操作中,一个小小的操作导致整个系统执行不下去,最后只能重启。

什么是异步编程

为了解决同步模型的问题,引入了异步编程的概念,意味着允许同一时刻执行多个任务。

异步编程模型意味着需要长时间运行的任务可以在后台运行,与主应用程序分开。系统可以自由地执行不依赖于该任务的其他工作,而不是阻止所有其他应用程序代码等待该长时间运行的任务完成。然后,一旦长时间运行的任务完成,我们会收到通知它已完成。

asyncio 库允许我们使用异步编程模型运行代码。 这让我们可以一次处理多个 I/O 操作,同时仍然允许我们的应用程序保持响应。

在 Python 3.4 中,asyncio 库中包含了装饰器和生成器 yield from 来定义协程(coroutine)。协程是一种方法,当我们有一个可能长时间运行的任务时可以暂停,然后在该任务完成时恢复。

协程执行完成后返回到调用者有一种新方法:通过 yield 控制。当协程的 yield 执行完成后立即回到了调用点,但是对协程的再次调用不会在起始处再次开始,相反,他们继续从最近停止处继续进行。

如下图所示:

def filter_even(numbers):
    for num in range(numbers):
        if (num % 2 == 0):
            yield num
even_number = filter_even(100)
print(list(even_number))

运行结果:

$ python yielddemo.py 
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98]

ayncio 版 Hello 程序

Python 3.5 版中,当关键字 async 和 await 显式添加到语言中时,该语言实现了对协程和异步编程的一流支持。 这种语法在 C# 和 JavaScript 等其他编程语言中很常见,它允许我们使异步代码看起来像是同步运行的。 这使得异步代码易于阅读和理解,因为它看起来像大多数软件工程师熟悉的顺序流程。 asyncio 是一个使用称为单线程事件循环的并发模型以异步方式执行这些协程的库。

利用 async/await 两个定义关键字定义协程,通过 asyncio 提供运行和管理协程的基础:

import asyncio
import time
async def main():
    print(f'{time.ctime()} Hello!')
    await asyncio.sleep(1.0)
    print(f'{time.ctime()} See you again!')
asyncio.run(main())

运行结果:

$ python asynciodemo.py 
Sat Jul  9 23:19:40 2022 Hello!
Sat Jul  9 23:19:41 2022 See you again!

asyncio 提供了一个 run() 函数来执行 async def 函数,然后从那里调用的所有其他协程,如 main() 函数中的 sleep() 函数。asyncio 不是多线程或多进程,而是并行运行代码。

JavaScript 中支持异步执行(浏览器,Nodejs,Electron 等)。在早期版本中,他们只是使用回调功能在异步操作完成后运行其他功能。

如何使用 asyncio

创建协程很简单,与创建普通的 Python 函数没有太大区别。唯一的区别是,我们不是使用 def 关键字,而是 使用 async def 。async 关键字将函数标记为协程,而不是普通的 Python 函数。

import asyncio
import time
def write(msg):
    print(msg, flush=True)
async def say1():
    await asyncio.sleep(1)
    write("Hello from 1")
async def say2():
    await asyncio.sleep(1)
    write("Hello from 2")
write("start")
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(
    say1(),
    say2()
))
write("exit")
loop.close()

运行该代码,可以看到 Hello from 1 运行 1 秒后运行 Hello from 2

$ python asyncoidemo2.py 
start
Hello from 1
Hello from 2
exit

run_until_complete 运行 say() 函数,解释器会逐行执行该函数的内容。当碰到 await 之后,解释器开始异步操作:这个操作为了循环将完成一些内部回调操作,这个回调操作是对开发人员隐藏的。但是现在,say1 开始后,它立即将控制返回到事件循环。所以,它启动异步 sleep 和控制循环,然后循环实际上已经开始启动 say2 函数。

当第一次异步 sleep 运行 1秒后,进入内部回调执行 say1 协程,下一个操作是打印 Hello from 1。打印后,它再次返回到活动循环。同时,从第二次睡眠开始,循环获得了有关完成第二次睡眠的事件。

所以接下来 Hello from 2 打印,然后第二种方法也返回。

run_until_complete(gather(l1,l2,l3)) 将阻止所有 l1,l2,l3 Coroutines:

请注意,7 和 9 事件可能会交换 - 如果您多次运行代码,您可能会注意到 Hello from 1 打印在 Hello from 2 之后。

  • event_loop 事件循环:程序开启一个无限循环,把一些函数注册到事件循环上,当满足事件发生的时候,调用相应的协程函数
  • coroutine 协程:协程对象,指一个使用 async 关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用。
  • task 任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含了任务的各种状态
  • future: 代表将来执行或没有执行的任务的结果。它和 task 上没有本质上的区别
  • async/await 关键字:python3.5 用于定义协程的关键字,async 定义一个协程,await 用于挂起阻塞的异步调用接口。

总结

本文首先介绍了同步编程和异步编程的概念,然后引出了协程的基本概念,写了 asyncio 版的 HelloWorld 程序,最后给出了 Python 中 asyncio 库的简易使用方法。

协程的优势在于多 IO 操作时能够有效提高程序速度,例如某些 HTTP 客户端,例如 aiohttps 调用服务器中就利用上了 asyncio 库。

参考链接:Async IO in Python: A Complete Walkthrough

以上就是Python使用Asyncio进行web编程方法详解的详细内容,更多关于Python Asyncio web编程的资料请关注我们其它相关文章!

(0)

相关推荐

  • python协程与 asyncio 库详情

    目录 1.asyncio 异步 I/O 库 异步函数的定义 事件循环 event_loop 创建 task 回调返回值 循环事件关闭 2.本节爬虫项目 前言: python 中协程概念是从 3.4 版本增加的,但 3.4 版本采用是生成器实现,为了将协程和生成器的使用场景进行区分,使语义更加明确,在 python 3.5 中增加了 async 和 await 关键字,用于定义原生协程. 1.asyncio 异步 I/O 库 python 中的 asyncio 库提供了管理事件.协程.任务和线程的

  • 浅谈Python协程asyncio

    一.协程 官方描述; 协程是子例程的更一般形式. 子例程可以在某一点进入并在另一点退出. 协程则可以在许多不同的点上进入.退出和恢复. 它们可通过 async def 语句来实现. 参见 PEP 492. 协程不是计算机内部提供的,不像进程.线程,由电脑本身提供,它是由程序员人为创造的, 实现函数异步执行. 协程(Coroutine),也可以被称为微线程,是一种用户太内的上下文切换技术,其实就是通过一个线程实现代码块相互切换执行.看上去像子程序,但执行过程中,在子程序内部可中断,然后转而执行别的

  • Python协程asyncio 异步编程笔记分享

    目录 1.事件循环 2.协程和异步编程 2.1 基本使用 2.2 await 2.3 Task对象 1.事件循环 可以理解成为一个死循环,去检查任务列表中的任务,如果可执行就去执行,如果检查不到就是不可执行的,那就忽略掉去执行其他可执行的任务,如果IO结束了(比如说去百度下载图片,下载完了就会变成可执行任务)再去执行下载完成之后的逻辑 #这里的任务是有状态的,比如这个任务已经完成或者正在执行或者正在IO等待 任务列表 = [ 任务1, 任务2, 任务3,... ] while True: 可执行

  • python 使用事件对象asyncio.Event来同步协程的操作

    事件对象asyncio.Event是基于threading.Event来实现的. 事件可以一个信号触发多个协程同步工作, 例子如下: import asyncio import functools def set_event(event): print('setting event in callback') event.set() async def coro1(event): print('coro1 waiting for event') await event.wait() print(

  • Python使用signal定时结束AsyncIOScheduler任务的问题

    在使用aiohttp结合apscheduler的AsyncIOScheduler模拟定点并发的时候遇到两个问题 在调度器scheduler.start()后,程序直接退出(在Jupiter中任务可以正常启动)如何在指定时间调用scheduler.shutdown()? (因为程序直接退出了) 原调试代码如下: from datetime import datetime, timedelta import aiohttp from apscheduler.schedulers.asyncio im

  • Python asyncio的一个坑

    我们先从一个常见的Python编程错误开始说起,我已经见过非常多的程序员犯过这种错误了: def do_not_raise(user_defined_logic): try: user_defined_logic() except: logger.warning("User defined logic raises an exception", exc_info=True) # ignore 这段代码的错误之处在哪里呢? 我们从Python的异常结构开始说起.Python中的异常基类有

  • Python使用Asyncio进行web编程方法详解

    目录 前言 什么是同步编程 什么是异步编程 ayncio 版 Hello 程序 如何使用 asyncio 总结 前言 许多 Web 应用依赖大量的 I/O (输入/输出) 操作,比如从网站上下载图片.视频等内容:进行网络聊天或者针对后台数据库进行多次查询.数据库查询可能会耗费大量时间,尤其是在该数据库处于高负载或查询很复杂的情况下. Web 服务器可能需要同时处理数百或数千个请求. I/O 是指计算机的输入和输出设备,例如键盘.硬盘驱动器,以及最常见的网卡.这些操作等待用户输入或从基于 Web

  • python爬虫之BeautifulSoup 使用select方法详解

    本文介绍了python爬虫之BeautifulSoup 使用select方法详解 ,分享给大家.具体如下: <html><head><title>The Dormouse's story</title></head> <body> <p class="title" name="dromouse"><b>The Dormouse's story</b></

  • 对python pandas 画移动平均线的方法详解

    数据文件 66001_.txt 内容格式: date,jz0,jz1,jz2,jz3,jz4,jz5 2012-12-28,0.9326,0.8835,1.0289,1.0027,1.1067,1.0023 2012-12-31,0.9435,0.8945,1.0435,1.0031,1.1229,1.0027 2013-01-04,0.9403,0.8898,1.0385,1.0032,1.1183,1.0030 ... ... pd_roll_mean1.py # -*- coding: u

  • 对python dataframe逻辑取值的方法详解

    我遇到的一个小需求,就是希望通过判断pandas dataframe中一列的值在两个条件范围(比如下面代码中所描述的逻辑,取小于u-3ε和大于u+3ε的值),然后取出dataframe中的所有符合条件的值,这个需求的解决与普通的iloc.loc.ix的方式不同,所以我想分享一下,希望可以帮到遇到这个困难的朋友们,下面是我的实例代码: doc[~((doc.iloc[:,141:142]<(mean_value-3*std_value))&(doc.iloc[:,141:142]>(me

  • 对Python获取屏幕截图的4种方法详解

    Python获取电脑截图有多种方式,具体如下: PIL中的ImageGrab模块 windows API PyQt pyautogui PIL中的ImageGrab模块 import time import numpy as np from PIL import ImageGrab img = ImageGrab.grab(bbox=(100, 161, 1141, 610)) img = np.array(img.getdata(), np.uint8).reshape(img.size[1]

  • 对Python的多进程锁的使用方法详解

    很多时候,我们需要在多个进程中同时写一个文件,如果不加锁机制,就会导致写文件错乱 这个时候,我们可以使用multiprocessing.Lock() 我一开始是这样使用的: import multiprocessing lock = multiprocessing.Lock() class MatchProcess(multiprocessing.Process): def __init__(self, threadId, mfile, lock): multiprocessing.Proces

  • 对Python之gzip文件读写的方法详解

    gzip文件读写的时候需要用到Python的gzip模块. 具体使用如下: # -*- coding: utf-8 -*- import gzip # 写文件 f_out = gzip.open("xxx.gz", "wb") # 读文件 # f_in = gzip.open("xxx.gz", "rb") for line in open("yyy.txt", "rb"): f_out

  • 对Python定时任务的启动和停止方法详解

    在python中我们可以使用APScheduler进行定时任务. APScheduler的具体编码这里就不介绍了.主要说下在终端中启动和停止任务. 一.运行计划任务的python脚本 如果我们在终端中直接执行的话,关闭终端窗口,Python任务就会中断,Python进程会被杀死,程序将停止运行.可以使用如下命令运行python脚本, python apschedulerscript.py & 这样执行后及时关闭终端窗口,程序依旧运行. 二.停止计划任务的Python脚本 如何停止呢,可使用如下方

  • 对python pandas读取剪贴板内容的方法详解

    我使用的Python3.5,32版本win764位系统,pandas0.19版本,使用df=pd.read_clipboard()的时候读不到数据,百度查找解决方法,找到了一个比较靠谱的 打开site-packages\pandas\io\clipboard.py 在 text = clipboard_get() 后面一行 加入这句: text = text.decode('UTF-8') 保存,然后就可以使用了 df=pd.read_clipboard() #变成正常的了 下次可以在其他地方复

  • python pandas修改列属性的方法详解

    使用astype如下: df[[column]] = df[[column]].astype(type) type即int.float等类型. 示例: import pandas as pd data = pd.DataFrame([[1, "2"], [2, "2"]]) data.columns = ["one", "two"] print(data) # 当前类型 print("----\n修改前类型:&quo

随机推荐