美文网首页
python 多进程

python 多进程

作者: 自由调优师_大废废 | 来源:发表于2019-12-16 19:46 被阅读0次

python 中的多进程 (工具包:multiprocessing )。

  • 我们可以利用multiprocessing.Process对象来创建一个进程对象。这个进程对象的方法和线程对象的方法也有 start(), run(), join() 等方法,其中 Process 进程对象的守护进程是通过设置 daemon 属性来完成的。

  • 实现方式一

from multiprocessing import Process
import time

def process1(name):
    print('你好 %s %s ' % (name, time.ctime()))

if __name__ == '__main__':
    process_list = []
    for i in range(5):
        p = Process(target=process1, args=('process1',))
        p.start()
        process_list.append(p)

    for i in process_list:
        p.join()

执行结果:


image.png

上面我们开启了5个子进程去执行函数,我们可以观察执行时间,是同时打印的。这里实现了真正的并行操作,就是多个 CPU 同时执行任务。进程是python中最小的资源分配单元,也就是进程中间的数据,内存是不共享的,每启动一个进程,都要独立分配资源和拷贝访问的数据,所以进程的启动和销毁的代价是比较大了,所以在实际中使用多进程,要根据服务器的配置来设定。

  • 实现方式二
from multiprocessing import  Process
import time

class MyProcess(Process):
    def __init__(self,name):
        super(MyProcess,self).__init__()
        self.name = name

    def run(self):
        print('你好 %s %s' % (self.name, time.ctime()))

if __name__ == '__main__':
    process_list = []
    for i in range(5):
        p = MyProcess('MyProcess')
        p.start()
        process_list.append(p)

    for i in process_list:
        p.join()

执行结果:


image.png

效果和第一种方式一样的,Python 多进程的实现方式和多线程的实现方式几乎一样。

Process类的其他方法

构造方法:
Process([group [, target [, name [, args [, kwargs]]]]])

  • group: 线程组
  • target: 要执行的方法
  • name: 进程名
  • args/kwargs: 要传入方法的参数
    实例方法:
  • is_alive():返回进程是否在运行,bool类型。
  • join([timeout]):阻塞当前上下文环境的进程程,直到调用此方法的进程终止或到达指定timeout(可选参数)。
  • start():进程准备就绪,等待CPU调度
  • run():strat()调用run方法,如果实例进程时未制定传入target,这star执行t默认run()方法。
  • terminate():不管任务是否完成,立即停止工作进程
    属性:
  • daemon:和线程的setDeamon功能一样
  • name:进程名字
  • pid:进程号

python 多进程通信

  • 进程是系统独立调度核分配系统资源(CPU、内存)的基本单位,进程之间是相互独立的,每启动一个新的进程相当于把数据进行了一次克隆,子进程里的数据修改无法影响到主进程中的数据,不同子进程之间的数据也不能共享,这是多进程在使用中与多线程最明显的区别。当然,python 也提供了多种方法实现了多进程中间的通信和数据共享。

进程队列 Queue

  • Queue 常在生成者消费者模式中使用,是线程安全的,是生产者和消费者中间的数据管道。在 python 多进程中,它其实就是进程之间的数据管道,实现进程通信。
from multiprocessing import Process,Queue

def fun1(queue,i):
    print('子进程 %s 开始 put 数据' %i)
    queue.put('子进程 %s 通过 Queue 通信' %i)

if __name__ == '__main__':
    queue = Queue()
    process_list = []
    for i in range(3):
        p = Process(target=fun1,args=(queue,i,))
        p.start()
        process_list.append(p)

    for i in process_list:
        p.join()

    print('主进程获取Queue数据')
    print(queue.get())
    print(queue.get())
    print(queue.get())
    print('结束')

执行结果:


image.png

Managers

  • Queue 只是实现了数据交互,并没实现数据共享,即一个进程去更改另一个进程的数据。需要用到 Managers。
from multiprocessing import Process, Manager
def fun1(dic,index):

    dic[str(index)] = index
    print(dic[str(index)])

if __name__ == '__main__':
    with Manager() as manager:
        # 注意字典的声明方式,不能直接通过{}来定义
        dic = manager.dict()
        process_list = []
        for i in range(5):
            p = Process(target=fun1, args=(dic,i))
            p.start()
            process_list.append(p)

        for p in process_list:
            p.join()
        print(dic.keys(), dic.values())
执行结果: image.png

主线中定义了一个字典,在子进程中,可以修改字典中的内容,实现进程间的数据共享,既可以共同修改同一份数据。

进程池

  • 进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。
  • 进程池中有两个方法:
    • apply:同步,一般不使用
    • apply_async:异步
from  multiprocessing import Process,Pool
import os, time, random
def fun1(name):
    print('Task %s (%s) start...' % (name, os.getpid()))
    start = time.time()
    time.sleep(random.random() * 3)
    end = time.time()
    print('Task %s finish %0.2f seconds.' % (name, (end - start)))
if __name__=='__main__':
    # 创建一个6个进程的进程池
    pool = Pool(6)
    for i in range(10):
        pool.apply_async(func=fun1, args=(i,))
    pool.close()
    pool.join()
    print('结束测试')

执行结果:
Pool 对象调用 join() 方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),调用 close() 之后就不能继续添加新的Process了。

相关文章

网友评论

      本文标题:python 多进程

      本文链接:https://www.haomeiwen.com/subject/gdwdnctx.html