你准备好“爬”了嘛(二)多进程

多进程

  1. 使用os模块中的fork构造进程;
    fork()方法只适用于Linux/Unix系统,是一个非常常见的系统调用的方法。

    forn()方法调用一次,返回两次。该方法调用时,操作系统将当前进程即父进程进行了复制,即子进程,这两个进程完全相同。在父进程中,返回的是子进程的ID;在子进程中,返回的是永远是0。
    测试程序fork_process.py
    需要主要的是这个程序只能在LInux/Unix系统上运行,在Windows系统上会报错。但是在Windows上可以通过安装子系统运行。
import os

if __name__ == '__main__':
    print("当前进程的ID:%s" % os.getpid())
    pid = os.fork()
    if pid < 0:
        print("创建进程失败!!!")
    elif (pid == 0):
        # 子进程中
        print("子进程的ID:%s,其父进程的ID:%s" %(os.getpid(), os.getppid()))
    else:
        # 父进程中
        print("父进程的ID:%s,其子进程的ID:%s" %(os.getpid(), pid))
  1. multiprocessing模块创建多进程
    fork()方法虽然方便,但是最大的缺陷在于其只能运行在Linux/Unix系统上,在Windows系统上可以使用multiprocessing模块提供的Process类。
    测试程序multiprocessing_process.py
  • 通过Process类创建进程
    Process类创建实例化对象,通过调用构造方法创建新进程。
    start()方法启动新创建的进程;
    join()方法的作用是在多进程执行时,其他进程必须等到调用join()方法的进程结束之后(或者超出规定的时间)才能继续执行;
  • 继承Process类创建进程
    run()方法在使用继承类创建新进程的时候需要用到,包含新进程需要执行的代码;
import os
from multiprocessing import Process

def run_proc(num):
    print("%s 号进程准备开始" %num)
    print("%s 号进程正在运行...ID为:%s" %(num, os.getpid()))
    print("%s 号进程已结束" %num)

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

    def run(self):
        print("%s 号进程准备开始" %self.num)
        print("%s 号进程正在运行...ID为:%s" %(self.num, os.getpid()))
        print("%s 号进程已结束" %self.num)

if __name__ == '__main__':
    print("进程正在运行...ID为:%s" %os.getpid())

    for i in range(3):
        p = Process(target=run_proc, args=(str(i), ))
        print("进程即将开始:")
        p.start()
        p.join()

    for i in range(3):
        my_process = MyProcess(i)
        print("进程即将开始:")
        my_process.start()
        my_process.join()

    print("进程结束")
  1. 进程池
    在multiprocessing模块中,Pool类可以提供指定数量的进程供用户调用,默认大小是CPU的核数。在初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中,如果进程池还没满的话,那么就创建一个新的进程来执行该请求;如果池中的进程数已达到最大进程数,那么该请求就只能等待,直到进程池中有进程结束,然后创建新的进程来处理该请求。
    测试程序multiprocessing_pool.py
# -*- coding: utf-8 -*-
from multiprocessing import Pool
import os, time, random

def run_mytask(num):
    print("进程%s正在运行...ID%s" %(num, os.getpid()))
    time.sleep(random.random()*2)
    print("进程%s结束" %num)

if __name__ == '__main__':
    print("当前进程 %s " %os.getpid())
    pool = Pool(processes=3)
    for i in range(4):
        pool.apply_async(run_mytask, args=(i, ))
    print("等待所有进程结束")
    pool.close()
    pool.join()
    print("所有进程结束")
  1. 进程间通信
    对于多进程而言,进程间的通信是十分关键的操作。
  • Queue通信方式
    Queue通信方式用于在多个进程之间实现通信。
    测试程序multiprocessing_queue.py
# -*- coding: utf-8 -*-
from multiprocessing import Process, Queue
import os, time, random

def run_writer(queue, nums):
    print("写进程正在运行 ID:%s" % os.getpid())
    for num in nums:
        queue.put(num)
        print("将 %s 放入 queue中..." % num)
        time.sleep(random.random())
    print("写进程结束 ID:%s" % os.getpid())

def run_reader(queue):
    print("读进程正在运行 ID:%s" % os.getpid())
    while not queue.empty():
        num = queue.get(True)
        print("从中取出数据 %s " % num)
        time.sleep(random.random())
    print("读进程结束 ID:%s" % os.getpid())
    # while True:
    #     if not queue.empty():
    #         num = queue.get(True)
    #         print("从中取出数据 %s " % num)
    #         time.sleep(random.random())
    #     else:
    #         break

if __name__ == "__main__":
    print("当前进程ID:%s" % os.getpid())
    queue = Queue()
    proc_writer1 = Process(target=run_writer, args=(queue, [1, 2, 3]))
    proc_writer2 = Process(target=run_writer, args=(queue, [4, 5, 6]))
    proc_reader = Process(target=run_reader, args=(queue, ))

    proc_writer1.start()
    proc_writer2.start()

    proc_reader.start()

    proc_writer1.join()
    proc_writer2.join()
    proc_reader.join()
    print("主进程结束 ID:%s" % os.getpid())
  • Pipe通信方式
    Pipe常用来在两个进程之间进行通信,其中两个进程分别位于管道的两端。
    测试程序multiprocessing_pipe.py
from multiprocessing import Process, Pipe
import time, os, random

def run_send(pipe, nums):
    print("发送进程正在运行 ID: %s" %os.getpid())
    for num in nums:
        pipe.send(num)
        time.sleep(random.random())

def run_recv(pipe):
    print("接收进程正在运行 ID: %s" %os.getpid())
    while True:
        print("接收到:%s" % pipe.recv())
        time.sleep(random.random())

if __name__ == '__main__':
    print("主进程ID %s正在运行..." % os.getpid())
    pipe = Pipe()
    proc_send = Process(target=run_send, args=(pipe[0], [i for i in range(4)]))
    proc_recv = Process(target=run_recv, args=(pipe[1], ))
    proc_send.start()
    proc_recv.start()
    proc_send.join()
    proc_recv.join()
    print("主进程ID %s结束..." % os.getpid())
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值