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…

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

支付宝
微信

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

查看所有标签

猜你喜欢:

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

Web应用安全权威指南

Web应用安全权威指南

德丸浩 / 赵文、刘斌 / 人民邮电出版社 / 2014-10 / 79

《web应用安全权威指南》系日本web安全第一人德丸浩所创,是作者从业多年的经验总结。作者首先简要介绍了web应用的安全隐患以及产生原因,然后详细介绍了web安全的基础,如http、会话管理、同源策略等。此外还重点介绍了web应用的各种安全隐患,对其产生原理及对策进行了详尽的讲解。最后对如何提高web网站的安全性和开发安全的web应用所需要的管理进行了深入的探讨。本书可操作性强,读者可以通过下载已......一起来看看 《Web应用安全权威指南》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换