python进程

进程

  • 进程又称重量级进程,正在执行中的程序称为进程。进程的执行会占用内存等资源。多个进程同时执行时,每个进程的执行都需要由操作系统按一定的算法(RR调度、优先数调度算法等)分配内存空间。
  • 并行与并发
    • 并行:在多核系统中,每个cpu执行一个进程,可以理解为cpu的数大于进程数,所有进程同时进行。

    • 并发:在操作系统中同时执行多个进程,可以理解为cpu的数小于进程数,有些进程会没有机会执行。

    • 并发与并行的区别:并行指两个或多个程序在同一时刻执行;并发指两个或多个程序在同一时间间隔内发生,可以理解为在表面上看是同时进行,但在同一时刻只有少于程序的总数的程序在执行,计算机利用自己的调度算法让这些程序分时的交叉执行,由于交换的时间非常短暂,宏观上就像是在同时进行一样。

1、进程简单实现

import multiprocessing

def demo_one():
    for i in range(3):
        print('子进程one- start --{}'.format(multiprocessing.current_process().name))

def demo_two():
    for i in range(3):
        print('子进程two- start --{}'.format(multiprocessing.current_process().name))


if __name__ == '__main__':
    print('主进程- start --{}'.format(multiprocessing.current_process().name))
    # 创建进程对象
    # target 传入调用函数
    p1 = multiprocessing.Process(target=demo_one)
    p2 = multiprocessing.Process(target=demo_two)
    p1.start()
    p2.start()
    print('主进程- end --{}'.format(multiprocessing.current_process().name))
  • 运行结果
主进程- start --MainProcess
主进程- end --MainProcess
子进程two- start --Process-2
子进程two- start --Process-2
子进程two- start --Process-2
子进程one- start --Process-1
子进程one- start --Process-1
子进程one- start --Process-1

2、进程间信息传递

  • 进程间不同享全局变量,进程间需要信息传递时,采用队列
  • 可以使用multiprocessing模块的Queue实现多进程之间的数据传递,Queue本身是一个消息列队程序
import multiprocessing
import time
from multiprocessing import Queue

def demo_one(q):
    for i in range(3):
        time.sleep(1)
        try:
            num = q.get()
            print(num)
        except:
            pass
        finally:
            print('子进程one- start --{}'.format(multiprocessing.current_process().name))

def demo_two(q):
    for i in range(3):
        q.put(6)
        time.sleep(0.5)
        print('子进程two- start --{}'.format(multiprocessing.current_process().name))


if __name__ == '__main__':
	q = Queue(3)  # Queue()若不知道队列内存储信息数量,默认是无限大,直到内存存满
    # 创建进程对象
    print('主进程- start --{}'.format(multiprocessing.current_process().name))
    # 进程间不共享全局变量,因此需要将初始化的`q`对象,传递到每一个子进程中
    p1 = multiprocessing.Process(target=demo_one, args=(q,))
    p2 = multiprocessing.Process(target=demo_two, args=(q,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    print('主进程- end --{}'.format(multiprocessing.current_process().name))
  • 执行结果
主进程- start --MainProcess
子进程two- start --Process-2
6
子进程one- start --Process-1
子进程two- start --Process-2
子进程two- start --Process-2
6
子进程one- start --Process-1
6
子进程one- start --Process-1
主进程- end --MainProcess

3、进程池Pool

  • 当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态成生多个进程,但如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以用到multiprocessing模块提供的Pool方法。

  • 初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务,请看下面的实例:

# 修改import中的Queue为Manager
from multiprocessing import Manager,Pool
import os,time,random

def reader(q):
    print("reader启动(%s),父进程为(%s)" % (os.getpid(), os.getppid()))
    for i in range(q.qsize()):
        print("reader从Queue获取到消息:%s" % q.get(True))

def writer(q):
    print("writer启动(%s),父进程为(%s)" % (os.getpid(), os.getppid()))
    for i in "python":
        q.put(i)

if __name__=="__main__":
    print("(%s) start" % os.getpid())
    q = Manager().Queue()  # 使用Manager中的Queue
    po = Pool()
    po.apply_async(writer, (q,))

    time.sleep(1)  # 先让上面的任务向Queue存入数据,然后再让下面的任务开始从中取数据

    po.apply_async(reader, (q,))
    po.close()
    po.join()
    print("(%s) End" % os.getpid())
  • 执行结果
(20052) start
writer启动(19584),父进程为(20052)
reader启动(11396),父进程为(20052)
reader从Queue获取到消息:p
reader从Queue获取到消息:y
reader从Queue获取到消息:t
reader从Queue获取到消息:h
reader从Queue获取到消息:o
reader从Queue获取到消息:n
(20052) End
multiprocessing.Pool常用函数解析:

apply_async(func[, args[, kwds]]) :使用非阻塞方式调用func(并行执行,堵塞方式必须等待上一个进程退出才能执行下一个进程),args为传递给func的参数列表,kwds为传递给func的关键字参数列表;
close():关闭Pool,使其不再接受新的任务;
terminate():不管任务是否完成,立即终止;
join():主进程阻塞,等待子进程的退出, 必须在close或terminate之后使用;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值