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 程序以确保协程安全是很重要的,协程安全是一个类似于线程安全和进程安全的概念,适用于协程。

本文由 mdnice 多平台发布

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 1. 忘记更新进度条:进度条需要在每一次循环迭代后更新,如果忘记更新,进度条将会停止在某一个位置,无法正确反映进度。 2. 进度条过长或过短:进度条需要正确反映任务的进度,如果进度条过长或过短,将无法正确反映任务的进度。 3. 进度条样式不美观:进度条作为用户界面的一部分,需要具备美观性,如果样式不美观,将影响用户体验。 4. 进度条速度过快或过慢:进度条需要根据任务的复杂程度和计算速度来设置速度,如果速度过快或过慢,将影响用户体验。 5. 进度条无法中止:有时候,用户需要中止任务,如果进度条无法中止,将会给用户带来困扰。 6. 进度条无法重新开始:有时候,用户需要重新开始任务,如果进度条无法重新开始,将会给用户带来困扰。 ### 回答2: Python实现文本进度条时,常见错误有以下几点: 1. 字符串拼接错误:在更新进度条时,使用字符串拼接来更新显示进度的字符串。这种方法会频繁创建新的字符串对象,导致大量的内存开销和性能下降。解决方法是使用字符串格式化或者列表拼接的方式来更新进度条字符串。 2. 进度计算错误:在计算进度条所占比例时,往往会出现计算错误的情况。例如,没有正确计算出当前任务的进度百分比,导致进度条显示不准确。解决方法是要确保通过正确的方式计算出当前任务的进度比例。 3. 更新频率错误:一些初学者在实现文本进度条时,频繁地更新进度条,这会导致屏幕输出过于频繁,给用户的体验造成困扰。解决方法是适度地控制更新的频率,可以使用时间间隔的方式来更新进度条。 4. 转义字符错误:在更新进度条时,在控制台输出时往往使用了转义字符来控制光标的位置。但是有些初学者容易出现转义字符使用错误的情况,导致输出的进度条格式混乱。解决方法是在使用转义字符时要仔细检查是否使用正确。 5. 异步更新错误:在多线程或异步编程中,如果没有正确处理更新进度条的同步问题,会导致多个线程同时更新进度条,造成进度条显示错乱。解决方法是使用线程锁或者其他同步机制来保证进度条的正确显示。 综上所述,Python实现文本进度条时需要注意以上几个常见错误,以保证进度条的正确显示和良好的用户体验。 ### 回答3: Python实现文本进度条时,常见错误包括以下几个方面: 1. 输出覆盖:在进度条更新时,如果直接使用print语句输出更新信息,会导致进度条上一行的内容被新的进度条信息覆盖。为了解决这个问题,可以使用'\r'特殊字符回车到行首,再输出新的进度条信息。 2. 进度计算错误:进度条的进度计算错误可能会导致进度条的显示不准确。例如,如果设定的总任务数与实际执行任务数不符,或者进度计算公式有误,导致进度条的百分比不准确。在编写代码时,需要确保进度计算的准确性。 3. 进度更新不及时:在某些情况下,进度条的更新可能不及时,导致用户无法即时看到进度变化。这可能是由于代码逻辑问题导致的,例如,程序在更新进度条之前耗时很长,或者进度更新频率过低。要解决这个问题,可以适当调整更新进度条的位置和频率。 4. 进度条长度超出终端宽度:当进度条的长度超过终端宽度时,可能会导致进度条显示不完全或错位。为了解决这个问题,可以通过获取终端宽度的方法来动态调整进度条的长度,以保证正确显示。 5. 多线程并行问题:当使用多线程或并行处理时,可能会导致进度条的更新出现错乱或混乱。这是因为多个线程同时更新进度条时,输出会相互干扰。为了解决这个问题,可以使用线程锁或其他同步机制,确保进度条的更新是有序的,避免线程间的竞争。 在实现文本进度条时,需要注意以上错误,并根据具体情况采取相应的解决方案,从而实现一个稳定、准确、美观的文本进度条。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值