当前位置: 首页 > article >正文

Python的并发编程-3

Python的并发编程

Python作为一门被广泛应用的编程语言,在并发编程领域也有其独特的优势。随着计算机和网络技术的不断发展,现代应用程序需求的复杂性也在不断增加,对于并发编程的需求也越来越迫切。Python的并发编程机制提供了多种方式,能够满足不同场景下的需求。

本文将介绍Python中的并发编程基本概念,生成器和协程,异步函数,以及aiohttp库等相关知识点。我们将从理论和实践两个角度来深入探讨这些概念,帮助读者更好地理解Python的并发编程机制,并能够应用到实际项目中。

并发编程基本概念

首先,我们需要了解并发编程中的一些基本概念。在这里,我们介绍两个概念:同步/异步和阻塞/非阻塞。

同步/异步

同步和异步是指程序执行的方式。同步指程序按照顺序执行,即代码的执行顺序和程序的执行顺序一致;异步指程序在执行过程中可以进行其他操作,即在进行某个操作的时候,程序可以同时进行其他操作。在异步编程中,程序可以通过回调函数或者协程等方式来处理异步操作的结果。

举个例子来说明,假设我们需要从网页上抓取一些数据,同步编程中,程序会依次发起请求并等待响应,直到所有请求都完成才会继续执行下一步。而在异步编程中,程序可以同时发起多个请求,并在等待响应的过程中处理其他操作,等到响应返回后再处理结果。

阻塞/非阻塞

阻塞和非阻塞是指程序等待操作结果的方式。阻塞指程序在等待某个操作的结果时,会一直等待,直到操作完成并返回结果;非阻塞指程序在等待某个操作的结果时,可以同时执行其他操作,不会一直等待。在阻塞编程中,程序通常需要使用多线程或者多进程等方式来处理多个任务;而在非阻塞编程中,程序可以使用异步编程的方式来处理多个任务。

生成器和协程

Python中的生成器和协程是并发编程中的两个重要概念,下面我们将分别介绍。

生成器

Python中的生成器是一种特殊的函数,可以被用来生成一个值序列,而不是一次性生成所有的值。生成器的特点是可以在需要的时候生成值,而不是一次性生成所有值并保存在内存中。这样可以节省内存,并且可以在需要时按需生成值。

下面是一个生成斐波那契数列的例子:

def fib(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

gen_obj = fib(20)
print(gen_obj)

for value in gen_obj:
    print(value)

输出:

<generator object fib at 0x106daee40>
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181

可以看出,生成器通过yield关键字实现对数列的生成,每次迭代生成一个数,而不是一次性生成所有数,可以节省内存。

协程

协程是一种轻量级的线程,可以在同一线程内实现多个子程序的协作,从而实现并发编程。协程的实现依赖于生成器,可以通过yield关键字和send方法实现协程的调度。

下面是一个简单的协程示例:

def calc_average():
    total, counter = 0, 0
    avg_value = None
    while True:
        curr_value = yield avg_value
        total += curr_value
        counter += 1
        avg_value = total / counter

def main():
    obj = calc_average()
    # 生成器预激活
    obj.send(None)
    for _ in range

异步函数

Python中的协程是基于生成器实现的,而异步函数则是Python 3.5及以上版本新增的语法特性,用于实现异步编程。异步函数可以通过asyncawait关键字来定义,其语法类似于普通函数,但是可以在函数内部使用await关键字来调用其他异步函数。

下面是一个异步函数的例子:

import asyncio

async def get_data():
    # 模拟异步操作
    await asyncio.sleep(1)
    return "data"

async def main():
    data = await get_data()
    print(data)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

在这个例子中,我们定义了一个异步函数get_data,并在其中使用了await asyncio.sleep(1)来模拟异步操作。在main函数中,我们使用await关键字来调用get_data函数,并在获取到结果后打印出来。最后,我们使用asyncio.get_event_loop()来获取事件循环对象,并使用loop.run_until_complete()方法来运行main函数。

异步函数的优点在于可以更好地利用CPU和IO资源,提升应用程序的性能和响应速度。但是在使用异步函数时需要注意,异步函数通常需要与事件循环配合使用,否则可能会出现无法预料的错误。

aiohttp库

aiohttp是Python中用于异步HTTP客户端/服务器编程的库,可以与异步函数和协程配合使用,提升网络请求的性能和响应速度。aiohttp库提供了与requests库类似的API接口,使用起来非常方便。

下面是一个使用aiohttp库的例子:

import aiohttp
import asyncio

async def fetch_page_title(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            html = await response.text()
            title = re.findall(r'<title>(.*?)</title>', html, re.S)[0].strip()
            print(title)

def main():
    urls = [
        '<https://www.python.org/>',
        '<https://www.jd.com/>',
        '<https://www.baidu.com/>',
        '<https://www.taobao.com/>',
        '<https://git-scm.com/>',
        '<https://www.sohu.com/>',
        '<https://gitee.com/>',
        '<https://www.amazon.com/>',
        '<https://www.usa.gov/>',
        '<https://www.nasa.gov/>',
    ]
    objs = [fetch_page_title(url) for url in urls]
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(objs))
    loop.close()

if __name__ == '__main__':
    main()

在这个例子中,我们定义了一个异步函数fetch_page_title,用于抓取网页的标题。通过aiohttp.ClientSession()方法创建一个ClientSession对象,并使用session.get()方法发起异步请求。在获取到响应后,我们通过await response.text()获取到HTML文本,并使用正则表达式解析出网页标题。最后,我们使用asyncio.wait()方法来并发运行多个异步函数。

可以看出,aiohttp库可以极大地简化异步网络编程的复杂性,提高开发效率和代码可读性。

总结

本文介绍了Python的并发编程机制中的基本概念,生成器和协程,异步函数,以及aiohttp库等相关知识点。并发编程对于现代应用程序的开发至关重要,Python提供了多种方式来实现并发编程,开发人员可以根据具体需求选择不同的方式来实现。同时,需要注意并发编程中的一些关键概念,如同步/异步和阻塞/非阻塞等,以确保程序的正确性和性能。


http://www.kler.cn/news/11667.html

相关文章:

  • nginx
  • js 身份证最后一位计算
  • SQL——多表连接查询
  • 一种供水系统物联网监测系统
  • ROS1学习笔记:常用可视化工具的使用(ubuntu20.04)
  • 【LeetCode: 剑指 Offer II 112. 最长递增路径 | 递归 | DFS | 深度优先遍历 | 记忆化缓存表】
  • Java——矩形覆盖
  • Flowable开源版和Flowable商业版有什么区别?
  • TCP网络连接的书写
  • 【MySQL面试题小结2023】
  • Linux文件权限
  • 借助Nacos配置中心实现一个动态线程池
  • 旅游酒店住宿
  • CF55D-Beautiful numbers (数位dp)
  • 自动化测试学习(七)-正则表达式,你真的会用吗?
  • Python循环实例
  • 爬虫日常练习-selenium登录12306
  • 2022年陕西省职业院校技能大赛“网络搭建与应用”赛项竞赛试题
  • Github创建组织(organization)
  • CTF-PHP反序列化漏洞1-基础知识
  • extern 关键字
  • 「Vue面试题」Vue项目中有封装过axios吗?主要是封装哪方面的?
  • 【分布式技术专题】「单点登录技术架构」一文带领你好好对接对应的Okta单点登录实现接口服务的实现落地
  • DHTMLX Gantt入门使用教程【引入】:如何开始使用 dhtmlxGantt
  • 51单片机和32单片机有什么区别?该从哪个开始入门学习?
  • 2023-03-18青少年软件编程(C语言)等级考试试卷(二级)解析
  • DStream是什么?怎样对DStream进行操作?
  • JS 正则匹配(RegExp)
  • UniverSeg:通用医学图像分割模型来了!
  • Python3 os.symlink() 方法、Python 质数判断