Python多处理示例

时间:2020-02-23 14:43:02  来源:igfitidea点击:

在本教程中,我们将通过示例学习Python多重处理。

Python多处理

如今,并行处理越来越受到关注。
如果您仍然不了解并行处理,请向维基百科学习。

随着CPU制造商开始向其处理器中添加越来越多的内核,创建并行代码是提高性能的好方法。
Python引入了多处理模块,使我们可以编写并行代码。

要了解此模块的主要动机,我们必须了解有关并行编程的一些基础知识。
阅读本文后,我们希望您能够收集有关此主题的一些知识。

Python多处理进程,队列和锁

python多重处理模块中有许多类可用于构建并行程序。
其中有三个基本类:"进程","队列"和"锁"。
这些类将帮助您构建并行程序。

但是在描述这些内容之前,让我们用简单的代码启动该主题。
为了使并行程序有用,您必须知道您的PC中有多少个内核。
Python Multiprocessing模块使您知道这一点。
以下简单代码将打印您PC中的内核数。

import multiprocessing

print("Number of cpu : ", multiprocessing.cpu_count())

以下输出可能因您的电脑而异。
对我来说,核心数是8。

Python多处理Process类

Python多处理" Process"类是一种抽象,它建立了另一个Python进程,提供了它运行代码的方式,并为父应用程序控制执行提供了一种方法。

属于Process类的两个重要函数是start()和join()函数。

首先,我们需要编写一个将由进程运行的函数。
然后,我们需要实例化一个流程对象。

如果我们创建一个过程对象,那么直到我们通过start()函数告诉它开始处理之前,什么都不会发生。
然后,该过程将运行并返回其结果。
之后,我们通过join()函数告诉过程完成。

如果没有join()函数调用,进程将保持空闲状态,并且不会终止。

因此,如果您创建许多流程而没有终止它们,则可能会面临资源短缺。
然后,您可能需要手动杀死它们。

重要的一件事是,如果您想在过程中传递任何参数,则需要使用" args"关键字参数。
以下代码将有助于理解Process类的用法。

from multiprocessing import Process

def print_func(continent='Asia'):
  print('The name of continent is : ', continent)

if __name__ == "__main__":  # confirms that the code is under main function
  names = ['America', 'Europe', 'Africa']
  procs = []
  proc = Process(target=print_func)  # instantiating without any argument
  procs.append(proc)
  proc.start()

  # instantiating process with arguments
  for name in names:
      # print(name)
      proc = Process(target=print_func, args=(name,))
      procs.append(proc)
      proc.start()

  # complete the processes
  for proc in procs:
      proc.join()

Python多处理Queue类

您具有有关计算机数据结构的基本知识,您可能也了解Queue。

Python多重处理模块提供了" Queue"类,该类正是先进先出数据结构。
它们可以存储任何pickle的Python对象(尽管最好是简单的对象),并且对于在进程之间共享数据非常有用。

当队列作为参数传递给流程的目标函数以使流程能够使用数据时,队列特别有用。
通过使用put函数,我们可以将数据插入队列中,然后使用get函数,可以从队列中获取数据。
请参见以下代码以获取快速示例。

from multiprocessing import Queue

colors = ['red', 'green', 'blue', 'black']
cnt = 1
# instantiating a queue object
queue = Queue()
print('pushing items to queue:')
for color in colors:
  print('item no: ', cnt, ' ', color)
  queue.put(color)
  cnt += 1

print('\npopping items from queue:')
cnt = 0
while not queue.empty():
  print('item no: ', cnt, ' ', queue.get())
  cnt += 1

Python多处理锁类

Lock类的任务非常简单。
它允许代码声明锁,以便在释放锁之前,没有其他进程可以执行类似的代码。
因此,Lock类的任务主要是两个。
一种是要求锁定,另一种是释放锁定。
要声明锁定,使用acquire()函数,并使用释放release()函数。

Python多处理示例

在这个Python多处理示例中,我们将所有知识融合在一起。

假设我们要完成一些任务。
为了完成该任务,我们将使用几个过程。
因此,我们将维持两个队列。
一个将包含任务,另一个将包含已完成任务的日志。

然后,我们实例化流程以完成任务。
请注意,python Queue类已经同步。
也就是说,我们不需要使用Lock类来阻止多个进程访问同一队列对象。
因此,在这种情况下,我们不需要使用Lock类。

下面是将任务添加到队列中,然后创建进程并启动它们,然后使用join()完成该过程的实现。
最后,我们从第二个队列中打印日志。

from multiprocessing import Lock, Process, Queue, current_process
import time
import queue # imported for using queue.Empty exception

def do_job(tasks_to_accomplish, tasks_that_are_done):
  while True:
      try:
          '''
              try to get task from the queue. get_nowait() function will 
              raise queue.Empty exception if the queue is empty. 
              queue(False) function would do the same task also.
          '''
          task = tasks_to_accomplish.get_nowait()
      except queue.Empty:

          break
      else:
          '''
              if no exception has been raised, add the task completion 
              message to task_that_are_done queue
          '''
          print(task)
          tasks_that_are_done.put(task + ' is done by ' + current_process().name)
          time.sleep(.5)
  return True

def main():
  number_of_task = 10
  number_of_processes = 4
  tasks_to_accomplish = Queue()
  tasks_that_are_done = Queue()
  processes = []

  for i in range(number_of_task):
      tasks_to_accomplish.put("Task no " + str(i))

  # creating processes
  for w in range(number_of_processes):
      p = Process(target=do_job, args=(tasks_to_accomplish, tasks_that_are_done))
      processes.append(p)
      p.start()

  # completing process
  for p in processes:
      p.join()

  # print the output
  while not tasks_that_are_done.empty():
      print(tasks_that_are_done.get())

  return True

if __name__ == '__main__':
  main()

根据任务的数量,代码将需要一些时间来显示输出。
以下代码的输出将不时变化。

Python多处理池

Python多处理池可用于跨多个输入值并行执行功能,从而跨进程分配输入数据(数据并行性)。
下面是一个简单的Python多处理池示例。

from multiprocessing import Pool

import time

work = (["A", 5], ["B", 2], ["C", 1], ["D", 3])

def work_log(work_data):
  print(" Process %s waiting %s seconds" % (work_data[0], work_data[1]))
  time.sleep(int(work_data[1]))
  print(" Process %s Finished." % work_data[0])

def pool_handler():
  p = Pool(2)
  p.map(work_log, work)

if __name__ == '__main__':
  pool_handler()

注意池的大小为2,所以两个work_log函数并行执行。
当函数处理之一完成时,它将选择下一个参数,依此类推。