进程

简介: 进程

多任务的执行方式

1.并发     (交替运行)


2.并行    (同时运行)

任务数大于内核数 并发执行
任务数小于等于内核数 并行执行

图片

进程的介绍

 在Python程序中,想要实现多任务可以使用进程来完成,进程是实现多任务的一种方式。


图片

                                            进程的概念


图片
一个正在运行的程序或者软件就是一个进程,它是操作系统进行资源分配的基本单位,也就是说每启

动一个进程,操作系统都会给其分配一定的运行资源(内存资源)

保证进程的运行。

进程,一个进程默认有一个线程,进程里面可以创建多个线程,
线程是依附在进程里面的,没有进程就没有线程。

多进程的使用

导入进程包

import multiprocessing
import time

跳舞任务

def dance():

for i in range(5):
    print("跳舞中...")
    time.sleep(0.2)

唱歌任务

def sing():

for i in range(5):
    print("唱歌中...")
    time.sleep(0.2)

if name == '__main__':

# 创建跳舞的子进程
# group: 表示进程组,目前只能使用None
# target: 表示执行的目标任务名(函数名、方法名)
# name: 进程名称, 默认是Process-1, .....
dance_process = multiprocessing.Process(group=None, target=dance, name= "myprogress1")
sing_process = multiprocessing.Process(target=sing)

# 启动子进程执行对应的任务
dance_process.start()
sing_process.start()

获取进程编号

导入进程包

import multiprocessing
import time
import os

跳舞任务

def dance():

# 获取当前进程(子进程)编号
dance_process_pid = os.getpid()
print("dance_process_pid:", dance_process_pid, multiprocessing.current_process())
# 获取当前进程的父进程编号
dance_process_parent_pid = os.getppid()
print("dance_process的父进程编号是:", dance_process_parent_pid)
for i in range(5):
    print("跳舞中...")
    time.sleep(0.2)

    # 扩展:根据进程编号强制杀死指定进程
    os.kill(dance_process_pid, 9)

唱歌任务

def sing():

sing_process_parent_pid = os.getppid()
print("sing_process_parent_pid的父进程编号是:", sing_process_parent_pid)
for i in range(5):
    print("唱歌中...")
    time.sleep(0.2)

获取当前进程(主进程)编号

main_process_pid = os.getpid()

print("main_process_id:", main_process_pid, multiprocessing.current_process())

if name == '__main__':

# 创建跳舞的子进程
# group: 表示进程组,目前只能使用None
# target: 表示执行的目标任务名(函数名、方法名)
# name: 进程名称, 默认是Process-1, .....
dance_process = multiprocessing.Process(group=None, target=dance, name= "my_process1")
sing_process = multiprocessing.Process(target=sing, name='my_process2')

# 启动子进程执行对应的任务
dance_process.start()
sing_process.start()



进程执行中带有参数

Progress类执行任务并给任务传参数有两种方式:

. args表示以元组的方式给执行任务传参

. kwargs表示以字典方式给执行任务传参

import multiprocessing

显示任务

def show_info(name, age):

print(name, age)

创建子进程

以元组方式传参,元组里面的元素顺序要和函数里面的参数顺序保持一致

sub_process = multiprocessing.Process(target=show_info, args=("hekang", 22))

sub_process = multiprocessing.Process(target=show_info, kwargs={'name':'杨凯文', 'age': 20})

以字典方式传参,字典里面的key要和函数里面的参数名保持一致,没有顺序要求

启动进程

if name == '__main__':

sub_process.start()

一个参数用元组传,一个参数用字典传

sub_process = multiprocessing.Process(target=show_info, args=("hekang",), kwargs={"age"=22}

进程之间不共享全局变量

import multiprocessing
import time

g_list = list() # => []

添加数据

def add_data():

for i in range(3):
    # 因为列表是可变类型,可以在原有内存的基础上修改数据,并且修改后内存地址不变
    # 所以不需要加global 申明
    # 加上global 表示申明要修改全局变量的内存地址
    g_list.append(i)
    print("added:", i)
    time.sleep(0.2)

读取数据

def read_data():

print(g_list)

添加数据的子进程

add_process = multiprocessing.Process(target=add_data)

读取数据的子进程

read_process = multiprocessing.Process(target=read_data)
if name == '__main__':

add_process.start()
read_process.start()

运行结果

added: 0

[]

added: 1

added: 2

遇到一个不太理解的Tracedback

当上面的代码

if name == '__main__':

add_process.start()
read_process.start()
将if name == '__main__':

去掉调用的时候报错

RuntimeError:

    An attempt has been made to start a new process before the

    current process has finished its bootstrapping phase.



    This probably means that you are not using fork to start your

    child processes and you have forgotten to use the proper idiom

    in the main module:



        if __name__ == '__main__':

            freeze_support()

            ...

    The "freeze_support()" line can be omitted if the program

    is not going to be frozen to produce an executable.

简单翻译下:

RuntimeError:

在当前进程完成了他的引导阶段之前试图去启动一个新进程。

这可能是表示你没有用fork方法启动子进程,并且你忘了用正确的姿势在main模块中:

if name == '__main__':

            freeze_support()

            ...

如果程序不会被冻结以生成可执行文件The "freeze_support()" 这行代码可以被忽略

至于具体为什么,根本原因,也没完全理解,大致就是windows创建进程没有fork方法,默认是spawn,而linux创建进程默认是fork方法。为了什么进程保护,代码必须放在if name == '__main__':下面。想要完全理解估计还要深入理解进程的概念,什么僵尸进程,孤儿进程类吧。

解决方法

加 if name == '__main__':

当.py文件被直接运行时,if name == '__main__'之下的代码块将被运行;

当.py文件以模块形式被导入时,if name == '__main__'之下的代码块不被运行。

相关文章
|
小程序 人工智能
EasyX之跳跳球
本文介绍了如何使用EasyX库开发一个跳跳球游戏,包括绘制小球和矩形、实现小球的起跳与下落、处理矩形的移动、解决小球二次起跳问题、判断游戏结束条件以及打印分数。
259 0
EasyX之跳跳球
|
机器学习/深度学习 编解码 自然语言处理
深度学习在图像处理中的应用与挑战
随着人工智能技术的迅猛发展,深度学习已成为推动技术革新的重要力量之一。特别是在图像处理领域,深度学习的应用不仅极大地提高了图像识别、分类和生成的精度,还拓展了新的研究方向和应用场景。本文旨在探讨深度学习在图像处理中的具体应用、所面临的主要挑战以及未来的发展趋势,以期为相关领域的研究提供参考和启示。
494 1
|
Web App开发 存储 运维
即学即会 Serverless | 初识 Serverless
Serverless 架构被越来越多的业务所采纳,成为其技术选型,大多数开发者已经跨越对 Serverless 概念了解,切实向落地实践出发。本文带大家一探究竟,为什么说 Serverless 可以帮助开发者聚焦核心业务价值,以及有哪些场景更适合 Serverless 架构!
|
机器学习/深度学习 人工智能 数据挖掘
参加Kaggle比赛的一般流程以及如何判断是否有条件参加
参加Kaggle比赛的一般流程以及如何判断是否有条件参加
1256 1
参加Kaggle比赛的一般流程以及如何判断是否有条件参加
|
存储 索引
Yolov3-spp系列 | yolov3spp的正负样本匹配
Yolov3-spp系列 | yolov3spp的正负样本匹配
531 0
Yolov3-spp系列 | yolov3spp的正负样本匹配
|
uml
IntelliJ IDEA - 提取参数对象重构
IntelliJ IDEA - 提取参数对象重构
746 0
IntelliJ IDEA - 提取参数对象重构
|
消息中间件 XML JSON
面对Spring Boot 3最低支持Java17如洪水猛兽袭来,何去何从
面对Spring Boot 3最低支持Java17如洪水猛兽袭来,何去何从
面对Spring Boot 3最低支持Java17如洪水猛兽袭来,何去何从
|
存储 算法 安全
一文带你了解CSRF、Cookie、Session和token,JWT之间的关系
1.Cookie和Session兄弟 由于HTTP协议本身是无状态的,也就是说同一个用户前一次HTTP请求和后一次HTTP请求时相互独立的,无法判断后一次请求的用户是不是刚才的用户。为了记录用户的状态,才有了Cookie。Cookie实际上以key-value键值对的形式存储了一些文本信息数据,它将数据保存在客户端(浏览器)。
1037 0
|
弹性计算 Ubuntu Linux
Ubuntu操作系统配置阿里云镜像方法二
Ubuntu操作系统配置阿里云镜像方法二
Ubuntu操作系统配置阿里云镜像方法二