Python多进程学习(一)

前情:这里只是单纯介绍 Python 中的多进程的程序开发,详细的内容还须要看操做系统知识。
复制代码

fork()

  • Python 的 os 模块封装了常见的系统调用,其中就包括 fork() ,能够在 Python 程序中轻松建立子进程,实现多进程。php

  • Unix/Linux 操做系统(好比常见的 Mac 咯)提供了一个 fork() 系统调用,它被调用一次,返回两次,由于操做系统自动把当前进程(称为父进程)复制了一份(称为子进程),而后分别在父进程和子进程内返回。ios

  • 子进程永远返回0,而父进程返回子进程的 ID,由于一个父进程能够 fork 出不少子进程,因此父进程要记下每一个子进程的 ID,而子进程只须要调用 getppid() 就能够拿到父进程的 ID。服务器

实战(Python3环境)微信

import os
print("正在运行的进程是 %s ..." % os.getpid())
pid = os.fork() # 若是是子进程返回0,而父进程返回子进程的ID,有了fork调用,一个进程在接到新任务时就能够复制出一个子进程来处理新任务,常见的Apache服务器就是由父进程监听端口,每当有新的http请求时,就fork出子进程来处理新的http请求。
print("\rpid 是 %s" %pid)
if pid == 0:
    print("子进程是 %s 和父进程是 %s." % (os.getpid(), os.getppid()))
else:
    print("在父进程 %s 中建立了子进程 %s." % (os.getpid(), pid))
复制代码

运行结果:app

正在运行的进程是 42322 ...
pid 是 46501
在父进程 42322 中建立了子进程 46501.
pid 是 0
子进程是 46501 和父进程是 42322.
复制代码

multiprocessing

multiprocessing 模块是跨平台版本的多进程模块。它提供了一个 Process 类来表明一个进程对象。因此无论在 Unix/Linux 操做系统,仍是 Windows 操做系统,均可以用 Python 编写多进程的程序。dom

实战yii

from multiprocessing import Process
import os

# 子进程要执行的代码
def my_proc(name):
    print("运行子进程 %s." % (os.getpid()))
# 至关于程序执行入口
if __name__=='__main__':
    print("父进程 %s." %os.getpid())
    p = Process(target=my_proc, args=('test',))  # 传入须要执行的函数和函数须要的参数,用start()启动,这种方式比fork()更简单
    print("子进程将要开始.")
    p.start()
    p.join()  # join() 能够等待子进程结束后继续往下执行,一般用于进程间同步
    print("子进程结束.")
复制代码

运行结果:async

父进程 42322.
子进程将要开始.
运行子进程 46580.
子进程结束.
复制代码

进程池 Pool

若是要启动大量的子进程,能够用进程池建立大量的子进程svg

实战函数

from multiprocessing import Pool
import os, time, random

def task(name):  
    print("运行任务 %s (%s)" %(name, os.getpid()))
    start = time.time()
    time.sleep(random.random() * 3)
    end = time.time()
    print("任务 %s 耗时 %.2f 秒" %(name, (end-start)))
    
if __name__ == "__main__":
    print("父进程 %s" %(os.getpid()))
    p = Pool(6)
    for i in range(10):
        p.apply_async(task, args=(i,))
    p.close()
    print("等待全部子进程完毕")
    p.join() # 对 Pool 对象调用 join() 方法会等待全部子进程执行完毕,调用 join() 以前必须先调用 close() ,调用 close() 以后就不能继续添加新的 Process 了
    print("全部子进程执行完毕")
复制代码

运行结果:

父进程 42322
运行任务 2 (43382)
运行任务 1 (43381)
运行任务 3 (43383)
运行任务 0 (43380)
运行任务 4 (43384)
运行任务 5 (43385)
任务 4 耗时 0.05 秒
运行任务 6 (43384)
等待全部子进程完毕
任务 5 耗时 0.26 秒
运行任务 7 (43385)
任务 1 耗时 0.57 秒
运行任务 8 (43381)
任务 7 耗时 0.96 秒
运行任务 9 (43385)
任务 8 耗时 1.03 秒
任务 3 耗时 2.00 秒
任务 0 耗时 2.07 秒
任务 6 耗时 2.26 秒
任务 2 耗时 2.70 秒
任务 9 耗时 2.61 秒
全部子进程执行完毕
复制代码

任务 2,1,3,0,4,5是马上执行的,而其余任务要等待前面某个任务完成后才执行,这是由于 Pool 的大小设置为6,所以,最多同时执行6个进程,Pool 的默认大小是 CPU 的核数

子进程

不少时候,子进程并非自身,而是一个外部进程。咱们建立了子进程后,还须要控制子进程的输入和输出。subprocess 模块可让咱们很是方便地启动一个子进程,而后控制其输入和输出。

进程间通讯

Process 之间确定是须要通讯的,操做系统提供了不少机制来实现进程间的通讯。Python 的 multiprocessing 模块包装了底层的机制,提供了 QueuePipes 等多种方式来交换数据。

实战

from multiprocessing import Process, Queue
import os, time, random

# 往 queue 里写内容
def write(q):
    print("写内容的进程: %s" %os.getpid())
    for v in 'ABC':
        print("把 %s 写进队列..." %v)
        q.put(v)
        time.sleep(random.random())
        
# 从 queue 里读内容
def read(q):
    print("读内容的进程: %s" %os.getpid())
    while True:
        v = q.get(True)
        print("从队列中读 %s." %v)

if __name__=="__main__":
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    pw.start()
    pr.start()
    pw.join() # 等待 pw 结束:
    pr.terminate() # pr 进程里是死循环,只能强行终止
复制代码

运行结果:

写内容的进程: 46049
读内容的进程: 46050
把 A 写进队列...
从队列中读 A.
把 B 写进队列...
从队列中读 B.
把 C 写进队列...
从队列中读 C.
复制代码

本文参考(不分前后顺序):

廖雪峰的官方网站:www.liaoxuefeng.com/wiki/101695…

但愿看客老爷打赏些喝茶钱

支付宝

支付宝

微信

微信
相关文章
相关标签/搜索