Python 异步: 常见错误(22)

简介: Python 异步: 常见错误(22)

动动发财的小手,点个赞吧!

本节举例说明开发人员在 Python 中使用 asyncio 时遇到的一般错误。

1. 尝试通过调用协程来运行协程

asyncio 初学者遇到的最常见错误是像调用函数一样调用协程。

例如,我们可以使用“async def”表达式定义协程:

# custom coroutine
async def custom_coro():
    print('hi there')

然后初学者将尝试像函数一样调用这个协程,并期望打印消息被报告。

...
# error attempt at calling a coroutine like a function
custom_coro()

像调用函数一样调用协程不会执行协程体。相反,它将创建一个协程对象。然后可以在 asyncio 运行时中等待该对象,例如事件循环。

我们可以使用 asyncio.run() 函数启动事件循环来运行协程。

...
# run a coroutine
asyncio.run(custom_coro())

或者,我们可以暂停当前协程并使用“await”表达式调度另一个协程。

...
# schedule a coroutine
await custom_coro()

2. 不要让协程在事件循环中运行

如果协程未运行,您将收到如下运行时警告:

sys:1: RuntimeWarning: coroutine 'custom_coro' was never awaited

如果您创建协程对象但不安排它在 asyncio 事件循环中执行,就会发生这种情况。

例如,您可能会尝试从常规 Python 程序中调用协程:

...
# attempt to call the coroutine
custom_coro()

这不会调用协程。相反,它将创建一个协程对象。

...
# create a coroutine object
coro = custom_coro()

如果您不允许此协程运行,您将收到运行时错误。正如我们在上一节中看到的,您可以通过启动异步事件循环并将协程对象传递给它来让协程运行。

...
# create a coroutine object
coro = custom_coro()
# run a coroutine
asyncio.run(coro)

或者,在复合语句的一行中:

...
# run a coroutine
asyncio.run(custom_coro())

如果您在 asyncio 程序中遇到此错误,那是因为您已经创建了一个协程并且没有安排它执行。

这可以使用 await 表达式来实现。

...
# create a coroutine object
coro = custom_coro()
# suspend and allow the other coroutine to run
await coro

或者,您可以安排它作为任务独立运行。

...
# create a coroutine object
coro = custom_coro()
# schedule the coro to run as a task interdependently
task = asyncio.create_task(coro)

3. 使用低级 Asyncio API

初学者的一个大问题是他们使用了错误的 asyncio API。这很常见,原因有很多。

  • API 在最新版本的 Python 中发生了很大变化。
  • API 文档页面让事情变得混乱,显示了两个 API。
  • Web 上其他地方的示例混合使用不同的 API。

使用错误的 API 会使事情变得更冗长(例如更多代码)、更困难并且更难理解。

Asyncio 提供了两个 API。

  • 面向应用程序开发人员的高级 API(我们)
  • 面向框架和库开发人员(不是我们)的低级 API

较低级别的 API 为高级 API 提供了基础,包括事件循环的内部结构、传输协议、策略等。我们应该几乎总是坚持使用高级 API。我们在入门时绝对必须坚持使用高级 API。我们有时可能会深入研究低级 API 以实现特定结果。

如果您开始获取事件循环的句柄或使用“循环”变量来做事,那您就错了。通过高级 API 驱动 asyncio 一段时间。开发一些程序。熟悉异步编程和随意运行协程。

4. 过早退出主协程

asyncio 程序的一个主要混淆点是没有给任务足够的时间来完成。我们可以通过 asyncio.create_task() 方法安排许多协程在 asyncio 程序中独立运行。

主协程是 asyncio 程序的入口点,然后可以继续执行其他活动。如果主协程退出,则 asyncio 程序将终止。

即使有一个或多个协程作为任务独立运行,程序也会终止。这会让你措手不及。

您可以发出许多任务,然后让主协程恢复,期望所有发出的任务都在自己的时间内完成。相反,如果主协程没有其他事情可做,它应该等待剩余的任务。

这可以通过首先通过 asyncio.all_tasks() 函数获取一组所有正在运行的任务,从该集合中删除自身,然后通过 asyncio.wait() 函数等待剩余的任务来实现。

...
# get a set of all running tasks
all_tasks = asyncio.all_tasks()
# get the current tasks
current_task = asyncio.current_task()
# remove the current task from the list of all tasks
all_tasks.remove(current_task)
# suspend until all tasks are completed
await asyncio.wait(all_tasks)

5. 假设竞争条件和死锁是不可能的

并发编程具有特定于并发的故障模式的风险。这包括竞争条件和死锁等问题。

竞争条件涉及两个或多个并发单元同时执行相同的临界区并使资源或数据处于不一致或意外状态。这可能会导致数据损坏和数据丢失。

死锁是指并发单元等待永远不会发生的情况,例如资源变得可用。许多 Python 开发人员认为,使用 asyncio 中的协程不可能出现这些问题。

原因是任何时候在事件循环中只能运行一个协程。的确,一次只能运行一个协程。

问题是,协程可以挂起和恢复,并且可以在使用共享资源或共享变量时这样做。如果不保护关键部分,异步程序中可能会出现竞争条件。如果不仔细管理同步原语,就会发生死锁。

因此,创建 asyncio 程序以确保协程安全是很重要的,协程安全是一个类似于线程安全和进程安全的概念,适用于协程。

相关文章
|
2月前
|
人工智能 开发者 Python
Chainlit:一个开源的异步Python框架,快速构建生产级对话式 AI 应用
Chainlit 是一个开源的异步 Python 框架,帮助开发者在几分钟内构建可扩展的对话式 AI 或代理应用,支持多种工具和服务集成。
240 9
|
2月前
|
Python
深入理解 Python 中的异步操作:async 和 await
Python 的异步编程通过 `async` 和 `await` 关键字处理 I/O 密集型任务,如网络请求和文件读写,显著提高性能。`async` 定义异步函数,返回 awaitable 对象;`await` 用于等待这些对象完成。本文介绍异步编程基础、`async` 和 `await` 的用法、常见模式(并发任务、异常处理、异步上下文管理器)及实战案例(如使用 aiohttp 进行异步网络请求),帮助你高效利用系统资源并提升程序性能。
99 7
|
2月前
|
SQL 网络协议 安全
Python异步: 什么时候使用异步?
Asyncio 是 Python 中用于异步编程的库,适用于协程、非阻塞 I/O 和异步任务。使用 Asyncio 的原因包括:1) 使用协程实现轻量级并发;2) 采用异步编程范式提高效率;3) 实现非阻塞 I/O 提升 I/O 密集型应用性能。然而,Asyncio 并不适合所有场景,特别是在 CPU 密集型任务或已有线程/进程方案的情况下。选择 Asyncio 应基于项目需求和技术优势。
|
3月前
|
数据采集 JSON 测试技术
Grequests,非常 Nice 的 Python 异步 HTTP 请求神器
在Python开发中,处理HTTP请求至关重要。`grequests`库基于`requests`,支持异步请求,通过`gevent`实现并发,提高性能。本文介绍了`grequests`的安装、基本与高级功能,如GET/POST请求、并发控制等,并探讨其在实际项目中的应用。
89 3
|
4月前
|
NoSQL 关系型数据库 MySQL
python协程+异步总结!
本文介绍了Python中的协程、asyncio模块以及异步编程的相关知识。首先解释了协程的概念和实现方法,包括greenlet、yield关键字、asyncio装饰器和async/await关键字。接着详细讲解了协程的意义和应用场景,如提高IO密集型任务的性能。文章还介绍了事件循环、Task对象、Future对象等核心概念,并提供了多个实战案例,包括异步Redis、MySQL操作、FastAPI框架和异步爬虫。最后提到了uvloop作为asyncio的高性能替代方案。通过这些内容,读者可以全面了解和掌握Python中的异步编程技术。
71 0
|
5月前
|
关系型数据库 MySQL 数据处理
探索Python中的异步编程:从asyncio到异步数据库操作
在这个快节奏的技术世界里,效率和性能是关键。本文将带你深入Python的异步编程世界,从基础的asyncio库开始,逐步探索到异步数据库操作的高级应用。我们将一起揭开异步编程的神秘面纱,探索它如何帮助我们提升应用程序的性能和响应速度。
|
5月前
|
调度 Python
深入理解 Python 中的异步操作 | python小知识
在现代编程中,异步操作是一个非常重要的概念,尤其是在处理 I/O 密集型任务时。使用异步操作可以显著提高程序的性能和响应速度。Python 提供了 `async` 和 `await` 关键字,使得编写异步代码变得更加直观和简洁【10月更文挑战第8天】
62 2
|
5月前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
143 0
|
5月前
|
数据采集 前端开发 NoSQL
Python编程异步爬虫实战案例
Python编程异步爬虫实战案例
112 2
|
5月前
|
数据采集 JSON 网络协议
Python编程异步爬虫——aiohttp的使用
Python编程异步爬虫——aiohttp的使用
125 0

热门文章

最新文章

推荐镜像

更多