Python多处理简介

多处理程序包使用类似于线程模块的API支持生成过程。 它还提供本地和远程并发。 本教程将讨论Python中的多重处理,以及如何使用多重处理在进程之间进行通信并执行进程之间的同步以及日志记录。

多处理简介

如下所示,通过创建一个Process对象然后调用其start()方法来进行多处理。

from multiprocessing import Process


def greeting():
    print 'hello world'

if __name__ == '__main__':
    p = Process(target=greeting)
    p.start()
    p.join()

在上面的示例代码中,我们首先导入Process类,然后使用要运行的greeting函数实例化Process对象。

然后,我们告诉该过程开始使用start()方法,最后使用join()方法完成该过程。

另外,您还可以通过提供args关键字参数来将参数传递给函数,如下所示:

from multiprocessing import Process


def greeting(name):
    print 'hello' + " " + name

if __name__ == '__main__':
    p = Process(target=greeting, args=('world',))
    p.start()
    p.join()

让我们看一个更详细的示例,其中涵盖了我们上面讨论的所有概念。

在此示例中,我们将创建一个计算数字平方并将结果打印到控制台的过程。

from multiprocessing import Process


def square(x):

    for x in numbers:
        print('%s squared  is  %s' % (x, x**2))

if __name__ == '__main__':
    numbers = [43, 50, 5, 98, 34, 35]

    p = Process(target=square, args=('x',))
    p.start()
    p.join
    print "Done"
    
    
#result
Done
43 squared  is  1849
50 squared  is  2500
5 squared  is  25
98 squared  is  9604
34 squared  is  1156
35 squared  is  1225

您还可以同时创建多个进程,如下例所示,其中进程p1获取数字平方的结果,而第二个进程p2检查给定数字是否为偶数。

from multiprocessing import Process


def square(x):

    for x in numbers:
        print('%s squared  is  %s' % (x, x**2))


def is_even(x):

    for x in numbers:
        if x % 2 == 0:
            print('%s is an even number ' % (x))


if __name__ == '__main__':
    numbers = [43, 50, 5, 98, 34, 35]

    p1 = Process(target=square, args=('x',))
    p2 = Process(target=is_even, args=('x',))

    p1.start()
    p2.start()

    p1.join()
    p2.join()

    print "Done"
    
#result

43 squared  is  1849
50 squared  is  2500
5 squared  is  25
98 squared  is  9604
34 squared  is  1156
35 squared  is  1225
50 is an even number 
98 is an even number 
34 is an even number 
Done

流程之间的沟通

多重处理支持进程之间的两种通信通道:

  • 管子
  • Queue列

Queue列

Queue对象用于在进程之间传递数据。 它们可以存储任何可腌制的Python对象,您可以使用它们,如下例所示:

import multiprocessing


def is_even(numbers, q):
    for n in numbers:
        if n % 2 == 0:
            q.put(n)

if __name__ == "__main__":

    q = multiprocessing.Queue()
    p = multiprocessing.Process(target=is_even, args=(range(20), q))

    p.start()
    p.join()

    while q:
        print(q.get())

在上面的示例中,我们首先创建一个检查数字是否为偶数的函数,然后将结果放在队列的末尾。 然后,我们实例化一个队列对象和一个流程对象并开始流程。

最后,我们检查队列是否为空,如果不是,则从队列的最前面获取值并将其打印到控制台。

我们已经展示了如何使用队列在两个进程之间共享数据,结果如下所示。

# result

0
2
4
6
8
10
12
14
16
18

还需要注意的是,Python具有一个Queue模块,该模块位于进程模块中,用于在线程之间共享数据,这不同于多进程队列位于共享内存中,并且用于在进程之间共享数据。

管子

多处理中的管道主要用于进程之间的通信。 用法很简单:

from multiprocessing import Process, Pipe

def f(conn):
    conn.send(['hello world'])
    conn.close()

if __name__ == '__main__':
    parent_conn, child_conn = Pipe()
    p = Process(target=f, args=(child_conn,))
    p.start()
    print parent_conn.recv()   
    p.join()

Pipe()返回两个表示管道两端的连接对象。 每个连接对象都有send()recv()方法。 在这里,我们创建一个进程,该进程打印字符串hello world ,然后共享数据。

结果
# result

['hello world']

锁具

Locks通过确保一次仅执行一个进程来工作,从而阻止其他进程执行类似的代码。 这样就可以完成该过程,然后才能释放该锁。

下面的示例显示了Lock方法的非常简单的用法。

from multiprocessing import Process, Lock


def greeting(l, i):
    l.acquire()
    print 'hello', i
    l.release()

if __name__ == '__main__':
    lock = Lock()
    names = ['Alex', 'sam', 'Bernard', 'Patrick', 'Jude', 'Williams']

    for name in names:
        Process(target=greeting, args=(lock, name)).start()


#result
hello Alex
hello sam
hello Bernard
hello Patrick
hello Jude
hello Williams

在此代码中,我们首先导入Lock方法,获取它,执行打印功能,然后释放它。

记录中

多重处理模块还提供了对日志的支持,尽管日志包不使用锁,因此进程之间的消息最终可能在执行过程中被混淆。

日志的用法很简单:

import multiprocessing, logging
logger = multiprocessing.log_to_stderr()
logger.setLevel(logging.INFO)
logger.warning('Error has occurred')

在这里,我们首先导入日志记录和多处理模块,然后定义multiprocessing.log_to_stderr()方法,该方法执行对get_logger()的调用,并添加一个将输出发送至sys.stderr的处理程序。 最后,我们设置记录器级别和要传达的消息。

结论

本教程介绍了开始使用Python进行多处理的必要条件。 多处理克服了GIL(全局解释器锁定)的问题,因为它利用了子进程而不是线程的使用。

本教程未涵盖Python文档中的更多内容,因此随时访问Python多重处理文档并充分利用此模块的全部功能。

翻译自: https://code.tutsplus.com/tutorials/introduction-to-multiprocessing-in-python--cms-30281

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值