Python 异步多线程协程初探

简介: Python 异步多线程协程初探

   今天在知乎上看到一篇文章 为什么有人说 Python 多线程是鸡肋? 中Python中的多线程是单核多线程,是伪多线程!为什么会这么说?

 由于Python 中 GIL。正是这个锁能保证同时只有一个线程在运行。罪魁祸首::。但如果去掉GIL的 Python 在单线程条件下执行效率将近慢了2倍。~~如果一定要通过多线程利用多核,那只能通过C扩展来实现,不过这样就失去了Python简单易用的特点。

 当然,对于 IO 密集型的程序,Python目前对 多线程性能还是有很大地改善的。 Python 3.4引入的 asyncio 模块来实现“协程”。

协程其实也是一种线程,其开销比threading小。而且它是Python3.4引入的新标准库 asyncio。asyncio的编程模型是一个消息循环。需要从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,实现了异步IO。这里的EventLoop有点像线程池。

 这就使得很多 IO 操作有了更好的方式去解决,虽然Python没有真正意义上的多线程,但采用 Event Loop 来处理耗时的 IO 操作,效果非常好。

 下面简单聊聊多线程协程之间的协作:

 EventLoop 总是与 thread 共存,它只是负责接收事件,余下的由 thread 来解决,保证并发。

 下面举一个测试例子:

def task():
            for i in range(5):
                 time.sleep(1)
                 print("task--"+str(i))
        def run_loop_inside_thread(loop):
            loop.run_forever()
        new_loop = asyncio.new_event_loop()
        asyncio.set_event_loop(new_loop)
        loop = asyncio.get_event_loop()
        threading.Thread(target=run_loop_inside_thread, args=(loop,)).start()
        loop.call_soon_threadsafe(task)
        return "finish"

image.gif

上面的例子,主要是在主线程中创建一个new_loop,然后在另外的子线程中开启一个无限事件循环。主线程通过call_soon_threadsafe新注册协程对象。这样就能在子线程中进行事件循环的并发操作,同时主线程又不会被block。

如果想传参的话,则可如下面所写:(传参6到more_work方法中)

.call_soon_threadsafe(more_work, 6)

image.gif

其中:

event_loopasyncio 的起点,是执行所有事件的起点

通过 loop.run_forever() + loop.call_* 实现对事件的调度

 如果不加

new_loop = asyncio.new_event_loop()
asyncio.set_event_loop(new_loop)

image.gif

则会报错:RuntimeError: There is no current event loop in thread 'Thread-1'。为什么会这样?根据asyncio的文档介绍,asyncio的事件循环不是线程安全的,一个event loop只能在一个线程内调度和执行任务,并且同一时间只有一个任务在运行。

 处于非主线程时,还需要调用set_event_loop方法指定一个event loop对象,这样get_event_loop才会获取到被标记的event loop对象

 但如果你只是运行 一个只有主线程的demo 的话,会发现 asyncio.get_event_loop()来获取 event_loop,是没问题的。

 上面的例子中的call_soon_threadsafe是asynico在多线程情况下专门针对线程安全的调用的解决方案。一般如果event loop在主线程中运行的话,子线程是不能使用它来调度任务。

 值得注意点是:在非阻塞的情况下,多线程是同步的代表,而协程是异步的代表。二者都可以开启多个线程。在多线程中,多个线程会竞争谁先运行,一个等待结束也不会去通知主程序,这样没有章法的随机运行会造成一些资源浪费。而在协程中,多个线程(称为微线程)的调用和等待都是通过明确代码组织的。协程就像目标明确地执行一个又一个任务,而多线程则会在竞争过程中性能有所降低。



相关文章
|
9天前
|
数据采集 JSON 测试技术
Grequests,非常 Nice 的 Python 异步 HTTP 请求神器
在Python开发中,处理HTTP请求至关重要。`grequests`库基于`requests`,支持异步请求,通过`gevent`实现并发,提高性能。本文介绍了`grequests`的安装、基本与高级功能,如GET/POST请求、并发控制等,并探讨其在实际项目中的应用。
20 3
|
16天前
|
数据采集 存储 数据处理
Python中的多线程编程及其在数据处理中的应用
本文深入探讨了Python中多线程编程的概念、原理和实现方法,并详细介绍了其在数据处理领域的应用。通过对比单线程与多线程的性能差异,展示了多线程编程在提升程序运行效率方面的显著优势。文章还提供了实际案例,帮助读者更好地理解和掌握多线程编程技术。
|
27天前
|
并行计算 数据处理 调度
Python中的并发编程:探索多线程与多进程的奥秘####
本文深入探讨了Python中并发编程的两种主要方式——多线程与多进程,通过对比分析它们的工作原理、适用场景及性能差异,揭示了在不同应用需求下如何合理选择并发模型。文章首先简述了并发编程的基本概念,随后详细阐述了Python中多线程与多进程的实现机制,包括GIL(全局解释器锁)对多线程的影响以及多进程的独立内存空间特性。最后,通过实例演示了如何在Python项目中有效利用多线程和多进程提升程序性能。 ####
|
21天前
|
监控 JavaScript 前端开发
python中的线程和进程(一文带你了解)
欢迎来到瑞雨溪的博客,这里是一位热爱JavaScript和Vue的大一学生分享技术心得的地方。如果你从我的文章中有所收获,欢迎关注我,我将持续更新更多优质内容,你的支持是我前进的动力!🎉🎉🎉
19 0
|
21天前
|
数据采集 Java Python
爬取小说资源的Python实践:从单线程到多线程的效率飞跃
本文介绍了一种使用Python从笔趣阁网站爬取小说内容的方法,并通过引入多线程技术大幅提高了下载效率。文章首先概述了环境准备,包括所需安装的库,然后详细描述了爬虫程序的设计与实现过程,包括发送HTTP请求、解析HTML文档、提取章节链接及多线程下载等步骤。最后,强调了性能优化的重要性,并提醒读者遵守相关法律法规。
55 0
|
1月前
|
NoSQL 关系型数据库 MySQL
python协程+异步总结!
本文介绍了Python中的协程、asyncio模块以及异步编程的相关知识。首先解释了协程的概念和实现方法,包括greenlet、yield关键字、asyncio装饰器和async/await关键字。接着详细讲解了协程的意义和应用场景,如提高IO密集型任务的性能。文章还介绍了事件循环、Task对象、Future对象等核心概念,并提供了多个实战案例,包括异步Redis、MySQL操作、FastAPI框架和异步爬虫。最后提到了uvloop作为asyncio的高性能替代方案。通过这些内容,读者可以全面了解和掌握Python中的异步编程技术。
46 0
|
6月前
|
Go Python
使用python实现一个用户态协程
【6月更文挑战第28天】本文探讨了如何在Python中实现类似Golang中协程(goroutines)和通道(channels)的概念。文章最后提到了`wait_for`函数在处理超时和取消操作中的作
54 1
使用python实现一个用户态协程
|
3月前
|
调度 Python
python3 协程实战(python3经典编程案例)
该文章通过多个实战案例介绍了如何在Python3中使用协程来提高I/O密集型应用的性能,利用asyncio库以及async/await语法来编写高效的异步代码。
32 0
|
5月前
|
数据库 开发者 Python
实战指南:用Python协程与异步函数优化高性能Web应用
【7月更文挑战第15天】Python的协程与异步函数优化Web性能,通过非阻塞I/O提升并发处理能力。使用aiohttp库构建异步服务器,示例代码展示如何处理GET请求。异步处理减少资源消耗,提高响应速度和吞吐量,适用于高并发场景。掌握这项技术对提升Web应用性能至关重要。
89 10
|
5月前
|
数据处理 Python
深入探索:Python中的并发编程新纪元——协程与异步函数解析
【7月更文挑战第15天】Python 3.5+引入的协程和异步函数革新了并发编程。协程,轻量级线程,由程序控制切换,降低开销。异步函数是协程的高级形式,允许等待异步操作。通过`asyncio`库,如示例所示,能并发执行任务,提高I/O密集型任务效率,实现并发而非并行,优化CPU利用率。理解和掌握这些工具对于构建高效网络应用至关重要。
53 6