Python多进程学习(一)

栏目: Python · 发布时间: 5年前

内容简介:实战(Python3环境)运行结果:multiprocessing模块是跨平台版本的多进程模块。它提供了一个
前情:这里只是单纯介绍  Python  中的多进程的程序开发,详细的内容还需要看操作系统知识。
复制代码

fork()

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

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

  • 子进程永远返回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))
复制代码

运行结果:

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

multiprocessing

multiprocessing模块是跨平台版本的多进程模块。它提供了一个 Process 类来代表一个进程对象。所以不管在 Unix/Linux 操作系统,还是 Windows 操作系统,都可以用 Python 编写多进程的程序。

实战

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("子进程结束.")
复制代码

运行结果:

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

进程池 Pool

如果要启动大量的子进程,可以用 进程池 创建大量的子进程

实战

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…

希望看客老爷打赏些喝茶钱

支付宝
微信

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Effective Java

Effective Java

Joshua Bloch / Addison-Wesley Professional / 2018-1-6 / USD 54.99

The Definitive Guide to Java Platform Best Practices—Updated for Java 9 Java has changed dramatically since the previous edition of Effective Java was published shortly after the release of Jav......一起来看看 《Effective Java》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具