[Python]多任务编程--进程(二)

简介: [Python]多任务编程--进程(二)

3 获取当前父进程编号

os.getppid() 表示获取当前父进程编号

示例代码:

# 导入进程包
import multiprocessing
import time
# 导入获取进程编号相关的模块
import os
# 唱歌任务
def sing():
    print('sing(): ')
    # 获取当前进程的id
    sing_process_id = os.getpid()
    # 获取当前进程对象
    sing_process_object = multiprocessing.current_process()
    print(sing_process_object, sing_process_id)
    print('父进程编号:', os.getppid())
    for i in range(5):
        print('唱歌中...')
        time.sleep(0.2)
# 跳舞任务
def dance():
    print('dance(): ')
    # 获取当前进程的id
    dance_process_id = os.getpid()
    # 获取当前进程对象
    dance_process_object = multiprocessing.current_process()
    print(dance_process_object, dance_process_id)
    print('父进程编号:', os.getppid())
    for i in range(5):
        print('跳舞中...')
        time.sleep(0.2)
# 判断当前运行的是否为主进程
if __name__ == '__main__':
    print('main: ')
    # 获取当前进程的id
    main_process_id = os.getpid()
    # 获取当前进程对象
    main_process_object = multiprocessing.current_process()
    print(main_process_object, main_process_id)
    # 创建跳舞的子进程
    dance_process = multiprocessing.Process(group=None, target=dance, name='dance')
    # 创建唱歌的子进程
    sing_process = multiprocessing.Process(target=sing, name='sing')
    # 启动子进程
    dance_process.start()
    sing_process.start()

4 扩展

获取进程名

语法:

进程对象.name
# 导入进程包
import multiprocessing
import time
# 导入获取进程编号相关的模块
import os
# 唱歌任务
def sing():
    print('sing(): ')
    # 获取当前进程对象
    sing_process_object = multiprocessing.current_process()
    print('进程名:', sing_process_object.name)
    for i in range(5):
        print('唱歌中...')
        time.sleep(0.2)
# 判断当前运行的是否为主进程
if __name__ == '__main__':
    print('main: ')
    # 获取当前进程对象
    main_process_object = multiprocessing.current_process()
    print('进程名:', main_process_object.name)
    # 创建唱歌的子进程
    sing_process = multiprocessing.Process(target=sing, name='sing')
    # 启动子进程
    sing_process.start()

根据进程编号强制杀死指定进程

语法

import os
# 第二个参数为杀死进程的方式,9 -- 强制杀死进程
os.kill(要杀死的进程编号, 9)
# 导入进程包
import multiprocessing
import time
# 导入获取进程编号相关的模块
import os
# 唱歌任务
def sing():
    print('sing(): ')
    # 获取当前进程对象
    sing_process_object = multiprocessing.current_process()
    print('进程名:', sing_process_object.name)
    for i in range(5):
        print('唱歌中...')
        time.sleep(0.2)
        os.kill(os.getpid(), 9)
# 判断当前运行的是否为主进程
if __name__ == '__main__':
    print('main: ')
    # 获取当前进程对象
    main_process_object = multiprocessing.current_process()
    print('进程名:', main_process_object.name)
    # 创建唱歌的子进程
    sing_process = multiprocessing.Process(target=sing, name='sing')
    # 启动子进程
    sing_process.start()

进程执行带有参数的任务

1. 进程执行带有参数的任务的介绍

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

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

(2)kwargs 表示以字典方式给执行任务传参

2. args参数的使用

元组方式传参(args): 元组方式传参一定要和参数的顺序保持一致

使用元组的方式进行传参,如果参数只有一个,元组的第一个逗号不能省略。

import multiprocessing
# 显示信息的任务
def show_info(name, age):
    print(name, age)
if __name__ == '__main__':
    # 创建子进程
    # 向任务传参使用 args 元组方式传参
    show_info_process = multiprocessing.Process(target=show_info, args=('zs', 20))
    # 启动子进程
    show_info_process.start()

3. kwargs参数的使用

字典方式传参(kwargs): 字典方式传参字典中的key一定要和参数名保持一致

import multiprocessing
# 显示信息的任务
def show_info(name, age):
    print(name, age)
if __name__ == '__main__':
    # 创建子进程
    # 向任务传参使用 args 元组方式传参
    show_info_process = multiprocessing.Process(target=show_info, kwargs={'name': 'zs', 'age': 29})
    # 启动子进程
    show_info_process.start()

第一个参数的传递使用元组,第二个参数的传递使用字典:

import multiprocessing
# 显示信息的任务
def show_info(name, age):
    print(name, age)
if __name__ == '__main__':
    # 创建子进程
    # 向任务传参使用 args 元组方式传参
    show_info_process = multiprocessing.Process(target=show_info, args=('zs',), kwargs={'age': 29})
    # 启动子进程
    show_info_process.start()

进程的注意点

1. 进程的注意点介绍

(1)进程之间不共享全局变量

(2)主进程会等待所有的子进程执行结束再结束

2. 进程之间不共享全局变量

创建子进程会对主进程资源进行拷贝,也就是说子进程是主进程的一个副本,好比是一对双胞胎,之所以进程之间不共享全局变量,是因为操作的不是同一个进程里面的全局变量,是不同进程里面名字相同的全局变量。

Windows下多进程程序,如果在主进程中没有if __name__ == '__main__':,会报错,因为创建子进程会对主进程资源进行拷贝,也就是说,子进程的代码与主进程一模一样,当主进程调用子进程时,由于子进程中存在直接执行新建子进程和调用子进程的代码,会出现无限递归调用,所以会报错。如果加上if __name__ == '__main__':判断,不是主进程就不会执行新建子进程和调用子进程的代码。

import multiprocessing
import time
# 定义全局变量
g_list = list()
# 添加数据的任务
def add_data():
    for i in range(5):
        g_list.append(i)
        print("add:", i)
        time.sleep(0.2)
    # 代码执行到此,说明数据添加完成
    print("add_data:", g_list)
def read_data():
    print("read_data", g_list)
if __name__ == '__main__':
    # 创建添加数据的子进程
    add_data_process = multiprocessing.Process(target=add_data)
    # 创建读取数据的子进程
    read_data_process = multiprocessing.Process(target=read_data)
    # 启动子进程执行对应的任务
    add_data_process.start()
    # 主进程等待添加数据的子进程执行完成以后程序再继续往下执行,读取数据
    add_data_process.join()
    read_data_process.start()
    print("main:", g_list)
    # 总结: 多进程之间不共享全局变量

进程之间不共享全局变量的解释效果图:

3. 主进程会等待所有的子进程执行结束再结束

假如我们现在创建一个子进程,这个子进程执行完大概需要2秒钟,现在让主进程执行0.5秒钟就退出程序,查看一下执行结果,示例代码如下:

import multiprocessing
import time
# 定义进程所需要执行的任务
def task():
    for i in range(10):
        print("任务执行中...")
        time.sleep(0.2)
if __name__ == '__main__':
    # 创建子进程
    sub_process = multiprocessing.Process(target=task)
    sub_process.start()
    # 主进程延时0.5秒钟
    time.sleep(0.5)
    print("over")
    exit()
    # 总结: 主进程会等待所有的子进程执行完成以后程序再退出

4. 主进程结束整个程序结束

为了保证子进程能够正常的运行,主进程会等所有的子进程执行完成以后再销毁,设置守护主进程的目的是主进程退出子进程销毁,不让主进程再等待子进程去执行。

  1. 守护主进程:
  • 守护主进程就是主进程退出子进程销毁不再执行,主进程结束执行,整个程序结束执行。
  • 语法:子进程对象.daemon = True
  1. 子进程销毁:
  • 主进程要结束时候,将子进程销毁,子进程执行结束,整个程序结束。
  • 语法:子进程对象.terminate()

4.1 设置守护主进程:

在pycharm中可能执行不出效果,需要在终端执行代码。(Windows)

import multiprocessing
import time
# 定义进程所需要执行的任务
def task():
    for i in range(10):
        print("任务执行中...")
        time.sleep(0.2)
if __name__ == '__main__':
    # 创建子进程
    sub_process = multiprocessing.Process(target=task)
    # 设置守护主进程,主进程退出子进程直接销毁,子进程的生命周期依赖与主进程
    sub_process.daemon = True
    sub_process.start()
    time.sleep(0.5)
    print("over")
    # 总结: 主进程会等待所有的子进程执行完成以后程序再退出
    # 如果想要主进程退出子进程销毁,可以设置守护主进程或者在主进程退出之前让子进程销毁

4.2 主进程结束时子进程销毁:

在pycharm中可能执行不出效果,需要在终端执行代码。(Windows)

import multiprocessing
import time
# 定义进程所需要执行的任务
def task():
    for i in range(10):
        print("任务执行中...")
        time.sleep(0.2)
if __name__ == '__main__':
    # 创建子进程
    sub_process = multiprocessing.Process(target=task)
    sub_process.start()
    time.sleep(0.5)
    print("over")
    # 让子进程销毁
    sub_process.terminate()
    exit()
    # 总结: 主进程会等待所有的子进程执行完成以后程序再退出
    # 如果想要主进程退出子进程销毁,可以设置守护主进程或者在主进程退出之前让子进程销毁


相关文章
|
3天前
|
存储 对象存储 Python
Python|玩转 Asyncio 任务处理(1)
Python|玩转 Asyncio 任务处理(1)
15 5
|
1天前
|
机器学习/深度学习 人工智能 前端开发
Python中的模块化编程
【6月更文挑战第17天】Python模块化编程与软件架构设计的关键在于拆分任务到独立模块,提高代码的可维护性、可重用性和可扩展性。例如,学生管理系统可分解为录入、查询和删除模块。MVC和MVVM架构模式有助于组织代码,而微服务和函数式编程将在未来发展中扮演重要角色。通过示例代码,读者能学习如何实现这些概念,提升项目开发效率和质量。
146 56
|
4天前
|
安全 Java Python
GIL是Python解释器的锁,确保单个进程中字节码执行的串行化,以保护内存管理,但限制了多线程并行性。
【6月更文挑战第20天】GIL是Python解释器的锁,确保单个进程中字节码执行的串行化,以保护内存管理,但限制了多线程并行性。线程池通过预创建线程池来管理资源,减少线程创建销毁开销,提高效率。示例展示了如何使用Python实现一个简单的线程池,用于执行多个耗时任务。
17 6
|
5天前
|
Python Windows
在 Windows 平台下打包 Python 多进程代码为 exe 文件的问题及解决方案
在使用 Python 进行多进程编程时,在 Windows 平台下可能会出现将代码打包为 exe 文件后无法正常运行的问题。这个问题主要是由于在 Windows 下创建新的进程需要复制父进程的内存空间,而 Python 多进程机制需要先完成父进程的初始化阶段后才能启动子进程,所以在这个过程中可能会出现错误。此外,由于没有显式导入 Python 解释器,也会导致 Python 解释器无法正常工作。为了解决这个问题,我们可以使用函数。
13 5
|
8天前
|
运维 监控 API
自动化运维实践指南:Python脚本优化服务器管理任务
本文探讨了Python在自动化运维中的应用,介绍了使用Python脚本优化服务器管理的四个关键步骤:1) 安装必备库如paramiko、psutil和requests;2) 使用paramiko进行远程命令执行;3) 利用psutil监控系统资源;4) 结合requests自动化软件部署。这些示例展示了Python如何提升运维效率和系统稳定性。
28 8
|
7天前
|
数据挖掘 调度 开发者
Python并发编程的艺术:掌握线程、进程与协程的同步技巧
并发编程在Python中涵盖线程、进程和协程,用于优化IO操作和响应速度。`threading`模块支持线程,`multiprocessing`处理进程,而`asyncio`则用于协程。线程通过Lock和Condition Objects同步,进程使用Queue和Pipe通信。协程利用异步事件循环避免上下文切换。了解并发模型及同步技术是提升Python应用性能的关键。
28 5
|
6天前
|
Java 程序员
Java多线程编程是指在一个进程中创建并运行多个线程,每个线程执行不同的任务,并行地工作,以达到提高效率的目的
【6月更文挑战第18天】Java多线程提升效率,通过synchronized关键字、Lock接口和原子变量实现同步互斥。synchronized控制共享资源访问,基于对象内置锁。Lock接口提供更灵活的锁管理,需手动解锁。原子变量类(如AtomicInteger)支持无锁的原子操作,减少性能影响。
18 3
|
6天前
|
数据采集 自然语言处理 调度
【干货】python多进程和多线程谁更快
【干货】python多进程和多线程谁更快
12 2
|
6天前
|
开发者 Python
【干货】Python编程惯例
【干货】Python编程惯例
11 1
|
8天前
|
SQL 关系型数据库 MySQL
实时计算 Flink版产品使用问题之运行run-application --target kubernetes-application执行,通过进程的返回码来决定作业是否成功,任务返回码都是0,该怎么办
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。