【Python基础】多进程编程(进程间通信 、进程池等附上实例代码)

🌈欢迎来到Python专栏
🙋🏾‍♀️作者介绍:前PLA队员 目前是一名普通本科大三的软件工程专业学生
🌏IP坐标:湖北武汉
🍉 目前技术栈:C/C++、Linux系统编程、计算机网络、数据结构、Mysql、Python(目前在学)
🍇 博客介绍:通过分享学习过程,加深知识点的掌握,也希望通过平台能认识更多同僚,如果觉得文章有帮助,请您动动发财手点点赞,本人水平有限,有不足之处欢迎大家扶正~
🍓 最后送大家一句话共勉:知不足而奋进,望远山而前行。愿大家都能早日进大厂实现财富自由~
————————————————

1.进程及进程状态介绍

1.1进程

  • 程序:例如 xxx.py 这是程序,是一个静态的

  • 进程:一个程序运行起来后,代码+用到的资源称之为进程,它是操作系统分配资源的基本单元。

1.2进程状态

工作中,任务数往往大于 cpu 的核数,即一定有一些任务正在执行,而另外一些任务在等待 cpu 进行执行,因此导致了有了不同的状态
01

• 就绪态:运行的条件都已经满足,正在等在 cpu 执行
• 执行态:cpu 正在执行其功能
• 等待态:等待某些条件满足,例如一个程序 sleep 了,此时就处于等待态

top
ps
R 状态 运行S 状态 睡眠
看到 R 状态是两次采样之间的一个时间片变化分析计算
cat /proc/cpuinfo 查看 Linux 的 cpu 的核数

2.Linux下 进程管理

  • 启动进程:手工启动 调度启动

02
备注:
进程 process:是 os 的最小单元 os 会为每个进程分配大小为 4g 的虚拟内存空间,其中

1g 给内核空间 3g 给用户空间{代码区 数据区 堆栈区}

cat /proc/cpuinfo 查看 CPU 个数


ps 查看活动进程   ps –aux 查看所有的进程   ps-aux| grep 'aa'查找指定(aa)进程   ps –elf 可以显示父子进程关系
 
进程状态:执行  就绪  等待状态

03
ps -aux 看%cpu(cpu 使用量) %mem(内存使用量) stat 状态{S 睡眠 T 暂停 R 运行 Z僵尸}
top 显示前 20 条进程,动态的改变,按 q 退出

04
第一行分别显示:

05
平均负载(load average),一般对于单个 cpu 来说,负载在 0~1.00 之间是正常的,超过 1.00 须引起注意。在多核 cpu 中,系统平均负载不应该高于 cpu 核心的总数。

第二行分别显示:
06
第三行
07
第四行
08
第五行:

09
buffers 与 cached 区别:buffers 指的是块设备的读写缓冲区,cached 指的

是文件系统本身的页面缓存。他们都是 Linux 系统底层的机制,为了加速对磁盘的访问。

然后下面就是和 ps 相仿的各进程情况列表了

第六行:

PID 进程号

USER 运行用户PR
优先级,PR(Priority)优先级

NI 任务 nice 值

VIRT 进程使用的虚拟内存总量,单位 kb。VIRT=SWAP+RES

RES 物理内存用量
SHR 共享内存用量
S 该进程的状态。其中 S 代表休眠状态;D 代表不可中断的休眠状态;R 代表运行状态;Z 代表僵死状态;T 代表停止或跟踪状态

%CPU 该进程自最近一次刷新以来所占用的 CPU 时间和总时间的百分比

%MEM 该进程占用的物理内存占总内存的百分比

TIME+ 累计 cpu 占用时间
COMMAND 该进程的命令名称,如果一行显示不下,则会进行截取。内存中的进程会有一个完整的命令行

3.3 进程、线程对比

功能
• 进程,能够完成多任务,比如 在一台电脑上能够同时运行多个 QQ
• 线程,能够完成多任务,比如 一个 QQ 中的多个聊天窗口
定义的不同
• 进程是系统进行资源分配和调度的一个独立单位.

• 线程是进程的一个实体,是 CPU 调度和分派的基本单位,它是比进程更小的能独
立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

区别
• 一个程序至少有一个进程,一个进程至少有一个线程.
• 线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发性高。
• 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提
高了程序的运行效率
线线程不能够独立执行,必须依存在进程中

优缺点

线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;
而进程正相反

4.进程相关使用

  • 进程创建:
#!/usr/bin/python
# author X_Dragon
# E-mail:3270895551@qq.com
# @Time : 2023/11/21 11:03
from multiprocessing import  Process
import time
import os
# 子进程运行代码
def run_proc():
    while True:
        print('-----2-----')
        print("进程ID:", os.getpid())
        time.sleep(1)
if __name__ == '__main__':
    p=Process(target=run_proc)  # run_proc 传递时不可以加括号
    p.start()
    while True:
        print('----1-----')
        print("进程ID:", os.getpid())
        time.sleep(1)
  • 2.僵尸进程制作
#!/usr/bin/python
# author X_Dragon
# E-mail:3270895551@qq.com
# @Time : 2023/11/21 11:21
import os
from multiprocessing import Process
import time

def run_proc():
    print('我是子进程 pid={},ppid={}'.format(os.getpid(),os.getppid()))
    # 这段代码中的format()函数用于将字符串中的占位符替换为指定的值。在这个例子中,
    # {}是一个占位符,它将被format()函数替换为os.getpid()和os.getppid()的返回值。
    print('子进程结束')
if __name__ == '__main__':
    child=Process(target=run_proc)
    child.start()
    print('我是父进程,我的pid={},ppid={}'.format(os.getpid(),os.getppid()))


  • 3.进程传参
#!/usr/bin/python
# author X_Dragon
# E-mail:3270895551@qq.com
# @Time : 2023/11/22 10:17
from multiprocessing import Process
import os
import time
def run_pro(name,age,**kwargs):
    for i in range(10):
        print('子进程{} {} ,{}'.format(name, age, kwargs))
        time.sleep(0.2)
if __name__ == '__main__':
    p=Process(target=run_pro,args=("wangwu",10),kwargs={'408':120})
    p.start()
    time.sleep(1)
    p.terminate()  # 给子进程发信号杀掉它
    p.join()  # 一直等子进程,子进程结束,资源会被回收
    print('我是父进程')

  • 4.进程间对于全局变量的使用
#!/usr/bin/python
# author X_Dragon
# E-mail:3270895551@qq.com
# @Time : 2023/11/22 10:25
from multiprocessing import Process
import os
import time

nums=[11,22]
def work1():
    print('I am work1,{}'.format(os.getpid()))
    nums.append(33)
    time.sleep(2)
    print('work1 {}'.format(nums))
def work2():
    print('I am work2,{}'.format(os.getpid()))

    print(nums)
if __name__ == '__main__':
    p=Process(target=work1)
    p.start()
    time.sleep(1)
    # nums.append(44)
    print('I am parent,{}'.format(nums))
    p.join()
    p = Process(target=work2)
    p.start()
    p.join()
    print(nums)
"""

在多进程的环境中,
每个进程都有自己独立的地址空间,全局变量也在这个地址空间中。
因此,每个进程都有一份自己的全局变量副本,它们互相独立。
当一个进程修改自己的全局变量时,不会影响其他进程的全局变量。
这是因为进程之间是相互隔离的,它们不共享内存空间
"""

== 在多进程的环境中,
每个进程都有自己独立的地址空间,全局变量也在这个地址空间中。
因此,每个进程都有一份自己的全局变量副本,它们互相独立。
当一个进程修改自己的全局变量时,不会影响其他进程的全局变量。
这是因为进程之间是相互隔离的,它们不共享内存空间 ==

  • 5.使用使用queue在进程中通信
#!/usr/bin/python
# author X_Dragon
# E-mail:3270895551@qq.com
# @Time : 2023/11/22 10:36

from multiprocessing import Process, Queue
import time
def writer(q):
    for value in ['A', 'B', 'C']:
        print('Put %s to queue...' % value)
        q.put(value)
        time.sleep(1)

def reader(q:Queue):
    while True:
        if not q.empty():
            value = q.get(True)
            print('Get %s from queue.' % value)
            time.sleep(2)
        else:
            break

if __name__ == '__main__':
    q=Queue(10)
    pw=Process(target=writer,args=(q,)) #一个元素必须加逗号,才是元组
    pr=Process(target=reader,args=(q,))
    pw.start()
    time.sleep(1)
    pr.start()
    pw.join()
    pr.join()
  • 6.进程池使用
#!/usr/bin/python
# author X_Dragon
# E-mail:3270895551@qq.com
# @Time : 2023/11/22 10:40
from multiprocessing.pool import Pool

import os, time, random

def worker(msg):
    star_time=time.time()
    # print("%s开始执行,线程号:%d" % msg,os.getpid())
    print("%s开始执行,线程号:%d" % (msg, os.getpid()))
    time.sleep(random.random()*2)
    end_time=time.time()
    # print("%s执行完毕,线程号:%d,线程执行事件为%0.2f" % msg,os.getpid(),star_time-end_time)
    print("%s执行完毕,线程号:%d,线程执行事件为%0.2f" % (msg, os.getpid(), end_time - star_time))
if __name__ == '__main__':
    po=Pool(10)
    for i in range(10):
        # 每次循环都会用空闲出来的子进程去调用目标
        po.apply_async(worker,(i,))

    print("--------start----------")
    po.close()
    po.join()

    print("---------end------------")

本篇到这~觉得有用麻烦您动动发财小手点点赞
0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值