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 系列了; 如果我们成功完成,则执行回调函数(这取决于某些所需任务的成功完成); 否则,我们不必执行我们的回调函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迹忆客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值