Python 中的异步编程简介

[ad_1]

介绍

当我们谈论编码时,我们通常会考虑以同步方式编写代码。 很明显,我们听说人脑在专注于一项任务时工作得很好。 我不会说编写同步代码是次要的(尤其是对于菜鸟)是巧合。

同步代码一直是流行的并且仍然是编写代码的首选方式,因为它具有以下几个优点:

  • 容易明白
  • 更容易写。
  • 无需考虑在多个进程/线程/调用之间共享的资源。
  • 没有对僵局的威胁(那些不眠之夜)。

但是,同步代码很慢。 他们阻止执行连续的орerаtiоns,直到处理下的任务完成。

Web 服务预计会在几百毫秒或最多 5 秒内给出响应,以获得良好的用户体验。 庞大的机器学习模型需要处理数千兆字节的数据,而这些模型并不是一蹴而就的; 有多次迭代。

那么我们有哪些选择呢?

的范式 异步 在这种情况下,编程就派上用场了。 异步程序不等待代码执行,而是跳转到另一个任务并开始执行它(嗯,并非总是如此,但你明白了?)。

异步调用是由 раllel соmрuting 形成的,其中一个单元оf tаsk 从主要的аррliсаtiоn 线程单独运行,并通知调用线程它的соmрletiоn,失败,оr рrоgress。

让我们慢慢来。 我们将把这个主题分成两篇单独的文章来掌握这些主题。

让我们谈谈 Python How To

在这里,我们将讨论多处理和多线程方法。

多处理

通常,应用程序运行一个进程来执行任何任务,因此称为 单处理器 系统或应用程序。

然而,强大的 python 为我们提供了一个并行运行多个进程的选项。 这是什么意思?

考虑打开两个 python 终端并在其上运行代码,可以在一个终端上执行而无需等待另一个终端。

from multiprocessing import Process

import os

import time

import random

def getProcessInfo(title):
  print(title)
  print('module name:', __name__)
  print('parent process:', os.getppid())
  print('process id:', os.getpid())
  print('n')

def printOne(n: int = 10):
  getProcessInfo('printOne Function Info')
  for _ in range(n):
    time.sleep(random.randint(0, 3))
    print("One")

def printTwo(n: int = 10):
  getProcessInfo('printTwo Function Info')
  for _ in range(n):

    time.sleep(random.randint(0, 3))
    print("Two")

if __name__ == "__main__":
  procs = []

  # Create a Process for printOne function
  proc = Process(target=printOne, args=(10,))
  # Append the Process to the list of all Processes
  procs.append(proc)
  #Start the Process
  proc.start()

  # Create a Process for printTwo function
  proc = Process(target=printTwo)

  # Append the Process to the list of all Processes
  procs.append(proc)

  # Start the Process
  proc.start()

  # Wait until all the processes are executed
  for proc in procs:
    proc.join()

在这里,我们创建了两个函数,它们在运行时打印一个字符串。 如果我们检查输出,我们可以确认它们是独立运行的,不会相互等待。

这里发生了什么?

考虑我们有一台双核计算机,每台计算机都分配了一个内核。 这些方法在这些内核中独立运行。 这些 multiрrосessоrs 共享 соmрuter 总线、CPU сlосk、内存和 рeriрherаl 设备。

(如果进程多于核心,则另当别论,我们将单独讨论。)

多线程

多个进程听起来很酷,但遗憾的是,每次我们需要并行执行某些操作时,它们并不是非常理想。

我们知道我们的 CPU 有内核,它们充当虚拟的单个 CPU。 这些虚拟 CPU 具有 线程 在他们之中。 它们处理我们程序中指令序列的执行。

希望这个名字有意义吧? 又名运行多个线程。 多线程。

from threading import Thread

import os

import time

import random

def getProcessInfo(title):
  print(title)
  print('module name:', __name__)
  print('parent process:', os.getppid())
  print('process id:', os.getpid())
  print('n')

# will run on Thread 1
def printOne(n: int = 10):
  getProcessInfo('printOne Function Info')
  for _ in range(n):
    time.sleep(random.randint(0, 3))
    print("One")

# will run on Thread 2
def printTwo(n: int = 10):
  getProcessInfo('printTwo Function Info')
  for _ in range(n):
    time.sleep(random.randint(0, 3))
    print("Two")

if __name__ == "__main__":
  threads = []

  # Create a Thread for printOne function
  thread = Thread(target=printOne, args=(10,))

  # Append the Thread to the list of all Threads
  threads.append(thread)
  thread.start()

  # Create a Thread for printTwo function
  thread = Thread(target=printTwo)

  # Append the Thread to the list of all Threads
  threads.append(thread)
  thread.start()

  # Wait until all the threads are executed
  for thread in threads:
    thread.join()

请注意,这两个线程的进程相同。

现在,这里发生了什么?

在这里,我们有一个进程,而该进程又具有多个线程。 代码、数据和文件在线程之间共享,每个线程都有一个堆栈。

结论:

所以现在我们可以让我们的应用程序高效地使用 CPU 周期和线程。 然而,在谈到异步代码时,并不是所有的彩虹和独角兽。

  • 开发人员应该清楚地了解他们在做什么。
  • 使用异步代码并非易事,可读性也会受到影响。
  • 不要忘记死锁!

切记, 权力越大责任越大

[ad_2]

Related Posts