python高级编程之多进程01

进程

1. fork()

import os
pid = os.fork() # 系统遇到os.fork()会创建一个新的进程
if pid ==0:  # 子进程值=0,父进程返回子进程的ID
    print("哈哈哈")
else:
    print("哈哈哈2")

2. getpid(),getppid()

  • getpid()子进程
  • getppid()父进程

3. 多进程修改全局变量

多进程中,每个进程中所有数据(包括全局变量),都各自拥有一份,互不影响

4. 多次fork问题

  • 类似于细胞分裂遇到fork分裂一次
  • 父进程、子进程执行顺序没有规律,完全取决于操作系统的调度算法

5. 进程的创建-multiprocessing

multiprocessing模块提供了一个process类来代表一个进程对象

from multiprocessing import Process
import os

# 子进程要执行代码
def run_proc(name):
    print("子进程运行中,name=%s,pid=%d..." % (name, os.getpid()))


# 主进程
if __name__ == '__main__':
    print("父进程%d" % os.getpid())
    p = Process(target=run_proc, args=("test",))
    p.start()
    p.join()
  • 创建子进程的时候,值需要传入一个 可执行函数函数的参数,创建一个Process实例,用start()方法启动即可
  • join()方法可以等待子进程结束后再继续往下运行,通常用于进程间同步

from multiprocessing import Process
import os
from time import sleep


def run_proc(name, age, **kwargs):
    for i in range(10):
        print("子进程运行中,name=%s, age=%d, pid=%d" % (name, age, os.getpid()))
        print(kwargs)
        sleep(0.5)


if __name__ == '__main__':
    print("父进程%d" % os.getpid())
    p = Process(target=run_proc, args=("test", 18), kwargs={"m":20, "a":18})
    p.start()
    sleep(1)
    p.terminate()
    p.join()

6. Process子类

还可以集成Process累,每次实例化这个类的时候,就等同于实例化一个进程对象

from multiprocessing import Process
import os
import time


class Process_Class(Process):
    # 参数传递写在__init__方法中,另外因为重写了这个方法,Process类本身的属性也要实现,所以利用继承来完成
    def __init__(self, interval, group=None, target=None, name=None, args=(), kwargs={}):
        super().__init__(group=None, target=None, name=None, args=(), kwargs={})
        self.interval = interval

    # 方法实现写在run方法中
    def run(self):
        print("子进程(%s) 开始执行,父进程为(%s)" %(os.getpid(), os.getppid()))
        t_start = time.time()
        time.sleep(self.interval)
        t_stop = time.time()
        print("1(%s)执行结束,耗时%0.2f秒" % (os.getpid(), t_stop-t_start))


if __name__ == '__main__':
    t_start = time.time()
    print("当前程序进程(%s)" % os.getpid())
    p1 = Process_Class(2)
    p1.start()
    p1.join()  # 如果没有这句话的话主进程不会等待子进程,会一直往下走
    t_stop = time.time()
    print("2(%s)执行结束,耗时%0.2f" % (os.getpid(), t_stop-t_start))

7. 进程池

from multiprocessing import Pool
import time
import random


def worker(msg):
    t_start = time.time()
    time.sleep(random.random()*2)
    t_stop = time.time()
    print(msg, "执行完毕,耗时%0.2f" % (t_stop - t_start))


if __name__ == '__main__':
    # 创建进程池
    po = Pool(3)
    for i in range(10):
        # Pool.apply_async(要调用的目标,(传递给目标的参数元祖,))
        po.apply_async(worker, (i,))
    print("__start__")
    po.close() # 关闭进程
    po.join()
    print("__end__")

  • 堵塞方式必须等待上一个进程退出才能执行下一个进程

8. 进程之间通信- Queue

使用multiprocessing模块的Queue实现多进程之间的数据传递

from multiprocessing import Queue


q = Queue(3)  # 初始化一个Queue对象,最多可以接受3条put信息
q.put("消息1")
q.put("消息2")
print(q.full())
q.put("消息3")
print(q.full())


try:
    q.put("消息4", True, 2)
except:
    print("消息列队已满,已有消息数量:%s" % q.qsize())
try:
    q.put_nowait("消息4", True)
except:
    print("消息列队已满,已有消息数量:%s" % q.qsize())

# 推荐方式,先判断消息列队是否已满,再写入
if not q.full():
    q.put_nowait("消息4")

# 读取消息时,先判断消息队列是否为空,再读取
if not q.empty():
    for i in range(q.qsize()):
        print(q.get_nowait())

8.1 Process中的实例

在父进程中创建两个子进程,一个往Queue里写数据,另一个从Queue里读数据

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


def write(q):  # 读和写放在同一个队列上通信
    for value in ["a", "b", "c"]:
        q.put(value)
        time.sleep(random.random())


def read(q):
    while True:
        if not q.empty():
            value = q.get(True)
            print("get %s from queue." % value)
            time.sleep(random.random())
        else:
            break


if __name__ == '__main__':
    # 父进程创建Queue,并传递给各个子进程
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    # 启动子进程pw,写入
    pw.start()
    pw.join()  # 等待pw结束
    # 启动子进程pr,读取
    pr.start()
    pr.join()
    print("所有数据都写入并且读完")

8.2 进程池中的Queue

需要使用multiprocessing.Manger()中的Queue

from multiprocessing import Manager, Pool
import os


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


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


if __name__ == '__main__':
    print("主进程 %s start" % os.getpid())
    q = Manager().Queue()  # 使用 Manger中的Queue来初始化
    po = Pool()
    po.apply(writer, (q,))
    po.apply(reader, (q,))
    po.close()
    po.join()  # 让主线程等待子线程结束
    print("主线程 %s end" % os.getpid())
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值