Python 中的 Promise 系列
本篇文章将介绍如何用 Python 编写一系列 promise。 首先,我们将讨论 Python 中的异步编程。
接下来,我们将讨论 Python 中的回调函数。 最后,在进入实际主题之前,我们将简要讨论 Python 中的 try/except,然后讨论 Python 中的一系列 Promise。
Python 中的异步编程
本文希望您对操作系统线程有基本的了解。 如果对线程没有初步的了解,可以先阅读操作系统中的线程。
异步编程允许多个线程并行运行,而主程序(通常称为主/管理线程)可以创建多个工作线程。 通常,主线程等待工作线程,工作线程在完成任务后通知主线程。
与常规编程不同,异步函数暂停并允许并行运行其他函数(线程),而不是在竞争之前保持控制。
我们将讨论并给出一个 Python 异步编程的例子; 不过,最好先看看相关的同步代码。 此代码将有助于通过比较来加深理解。
def count():
for i in range(5):
print(i, end=' ')
def main():
count()
count()
count()
main()
在这里,我们依次调用了 3 次 count 函数。 输出符合预期。
0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
可以看到第一个计数函数的输出,接着是第二次调用计数函数的输出,最后是最后一个计数函数的输出。
Python 的 asyncio
库允许在 Python 中运行异步程序。 异步编程的第一个要求是将函数设计为可等待对象。
将标准函数转换为可等待对象有两个要求。 第一种是使用 async 关键字(在 def 关键字之前)创建异步函数而不是常规函数。
第二个需求是在异步函数内部调用sleep函数,挂起当前函数,控制其他函数。
sleep 语句是代码中函数准确进入挂起状态的特定点。 异步编程的第二个需求是在调用可等待对象(异步函数)的同时加入await; 否则会出错。
await
关键字告诉事件循环暂停当前函数,以便为其他函数提供运行时间。
第三个需求是调用 gather 函数并传递 awaitable
对象(异步函数)。 gather 函数按顺序但同时运行这些函数。
这意味着第一个函数首先启动,一段时间后,第二个函数也并行启动。 类似地,所有异步函数开始并发运行,一个接一个。
现在,让我们看看代码。
import asyncio
async def count():
for i in range(5):
print(i, end=' ')
await asyncio.sleep(0.5)
async def main():
await asyncio.gather(count(), count(), count())
if __name__ == "__main__":
asyncio.run(main())
在这里,我们将之前的代码转换为异步代码并添加了某些内容。 在第一行中,导入了 asyncio 库。
async 关键字添加在所有函数的开头。
睡眠函数调用被添加到计数函数中。 await
关键字被添加到所有函数调用中,包括 main 函数。
最后,在 main 中调用 gather
函数,其中多次调用 count
函数以将每个函数调用作为一个单独的线程进行演示。
使用 gather 函数,我们添加可等待对象以形成一组异步函数并发运行。 让我们看看这段代码的输出。
0 0 0 1 1 1 2 2 2 3 3 3 4 4 4
在输出中,您可以看到所有线程并行运行并产生异步输出,而不是一起运行。
您可能会混淆多次调用同一个函数; 这是另一个例子,我们有不同的功能并行运行。
import asyncio
async def count1():
for i in range(10):
print(i, end=' ')
await asyncio.sleep(0.5)
async def count2():
for i in range(50,60):
print(i, end=' ')
await asyncio.sleep(0.5)
async def main():
await asyncio.gather(count1(), count2())
asyncio.run(main())
此代码的输出是:
0 50 1 51 2 52 3 53 4 54 5 55 6 56 7 57 8 58 9 59
同样,这两个函数同时运行。
回调函数
回调被传递给另一个函数(作为参数)。 另一个函数应该在其定义的某处回调此函数。
但是,调用点取决于另一个函数的定义方式。
在这里,我们有一个与回调函数相关的简单编码示例。
import random as r
def callback1(s):
print(f'******* {s} *******')
def callback2(s):
print(f'^^^^^^^ {s} ^^^^^^^')
def print_through_callback(message, f1, f2):
if r.randint(0,1) == 0:
f1(message)
else:
f2(message)
def main():
print_through_callback("Callback Example", callback1, callback2)
main()
在这段代码中,我们的打印函数有三个参数。 第二个和第三个参数是一些函数名。
大体上,我们传递两个函数,代码随机调用一个。 如果多次运行此代码,您会看到这两个函数都是随机调用的。
在 Python 中try/except
Python 还提供异常处理。 在 Python 中,我们有一个 try 块来测试代码; 它有可能发生异常,在 except 块中,您可以处理异常。
我们都知道除以零是没有定义的,程序(几乎所有编程语言)都会崩溃; 当我们调用除以零操作时。 如果您不知道,请尝试此代码。
def main():
x = int(input('Enter any number:'))
print (2/x)
main()
输入零,看结果; 你的程序会崩溃。 代码崩溃是一件坏事,应该通过异常处理来避免。
查看异常处理的相同代码。
def main():
try:
x = int(input('Enter any number:'))
print (2/x)
except:
print ('Divide by zero is not defined')
main()
您应该运行此代码并输入非零值; 你会得到除法运算的结果,写在 print (2/x)
里面; 如果您输入零,程序将给出消息除以零未定义而不是崩溃。
Python 中的 Promise 系列
回调函数与普通函数相同; 但是,它们的用途不同。
考虑需要大量时间执行的重量级函数。 通常,这些函数是异步的。
异步函数将在后台执行,并在特定时间后完成,而其他函数将并行启动。 但是,如果你想在完成一些重量级的功能后运行一些功能,选择是使用回调函数。
但是,完成此类任务存在问题。 如果任务在完成之前抛出异常怎么办?
为了确保在成功完成任务后调用该函数,需要承诺和异步编程。
Promises
promise
是一个对象,表示异步函数的成功或不成功(失败)完成。
Promise 对象还表示异步函数的结果值。 Promise 用于管理与多个回调相关的问题。
我们可以使用 promise API 在 Python 中执行一系列的 promise。 然而,我们可以通过 async/await 在 Python 中达到同样的目的。
要在 Python 中使用异步函数实现,我们必须使用带有异步函数的 asyncio 库。 我们可以使用上面已经描述的 await 关键字顺序调用函数。
最后,我们使用 try/except 块。 首先,查看代码和输出。
稍后,我们将解释 try/except 块的用途。
import asyncio
import random as r
async def f1(x):
await asyncio.sleep(1)
return x ** 2
async def f2(x):
await asyncio.sleep(1)
return x / 2
async def f3(x):
if r.randint(0, 1) == 0:
return x
raise ValueError(x)
async def run():
try:
value = await f3(await f2(await f1(r.randint(5,9))))
except ValueError as exception:
print('Exception Occurred:', exception.args[0])
else:
print('No Exception:', value)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
loop.close()
以下是上述 Python 脚本 5 次运行的组合输出。
No Exception: 12.5
Exception Occurred: 12.5
Exception Occurred: 32.0
No Exception: 18.0
No Exception: 40.5
输出只是描述我们在某些异步操作中可能成功或失败。 因此,我们可以在 try 块中的函数调用之后放置一个回调函数的语句。
如果成功完成,代码将执行回调函数。 失败时,控件将转到 except 块并忽略回调函数。
这样,我们就可以处理Python中的 promises 系列了; 如果我们成功完成,则执行回调函数(这取决于某些所需任务的成功完成); 否则,我们不必执行我们的回调函数。
相关文章
Python 中的队优先级列比较器
发布时间:2023/06/19 浏览次数:192 分类:Python
-
本文将研究使用 Python 开发自定义优先级队列。 除此之外,我们还将学习如何将自定义比较器函数与优先级队列一起使用。Python 中的优先级队列
为 Python 创建别名
发布时间:2023/06/19 浏览次数:194 分类:Python
-
在这种情况下,您决定保留两个版本的 Python。 在本文中,我们将学习如何在拥有两个 Python 版本的情况下创建别名。为 Python 创建别名
从 Python 使用 DLL 文件
发布时间:2023/06/19 浏览次数:60 分类:Python
-
本篇文章将介绍使用 Python 程序中的 DLL 文件。使用 ctypes 库从 Python 使用 DLL 文件 ctypes 是一个在 Python 中提供与 C 兼容的数据类型的外部函数库。
在 Python 中将数据类转换为 JSON
发布时间:2023/06/19 浏览次数:63 分类:Python
-
在本篇文章中,我们将了解 Python 如何支持 JSON 来为每个 JSON 根节点创建数据类。 我们还将学习 dataclass 作为 Python 字典的实现。在 Python 中将数据类转换为 JSON
Python Dict 与 Asdict
发布时间:2023/06/19 浏览次数:177 分类:Python
-
obj._dict_() 背后的概述至少比 dataclasses.asdict(obj) 快十倍。Python 3.7引入了dataclasses库,让我们可以制作专门用于数据存储的结构化类。
在 Qt Creator 中开发 Python 应用程序
发布时间:2023/06/19 浏览次数:60 分类:Python
-
Qt Creator 是一个跨平台的 IDE,可让您为桌面、嵌入式和移动设备创建软件。 它在 Linux、macOS 和 Windows 操作系统上运行。本篇文章将介绍使用 Qt Creator 应用程序开发 Python 应用程序。
Python if-else 速记
发布时间:2023/06/19 浏览次数:72 分类:Python
-
本文解释了 Python 中 if-else 语句的简写表示法,它使用条件、正值和负值作为其组成部分。
Python 地址解析器
发布时间:2023/06/19 浏览次数:101 分类:Python
-
本文将向您展示如何使用 Python 解析地址。 我们将使用 pyparsing 库手动解析地址,并使用函数或 pyparsing 获取 CSV 文件中的地址。
使用 Python 列出串口
发布时间:2023/06/19 浏览次数:53 分类:Python
-
在本文中,我们将讨论使用串口或 com 端口的通信。 我们将深入探索 Python 包,以帮助我们获得系统的可用通信端口。