11 Python 进程与线程编程

简介: 11 Python 进程与线程编程

1、什么是进程和线程?

首先我们要知道进程是系统进行资源分配和调度的基本单位,而线程是进程的一个执行路径,一个进程中至少有一个线程,进程中的多个线程共享进程的资源。

比如我们打开一个 csdn 的软件,其实就打开一个叫csdn 的进程,既然一个进程汇中至少要有一个线程,那肯定就会有多线程,什么是多线程?

1、多线程是指从软硬件上实现多条执行路径的技术。


2、多线程用在哪里,有什么好处?

例如铁路12306购票系统。

例如过年回家抢票,不可能只有你一个人在买票,那每个人进来的时候都要有一个执行路径,那这个之后就需要用到多线程。

2、创建多进程

在python 中创建多进程我们要知道一个模块-- multiprocessing

函数

介绍

参数

返回值

Process

创建一个进程

target(函数),args(函数的参数)

进程对象

start

执行进程

join

阻塞程序

kill

杀死进程

is_alive

进程是否存活

bool

接下来我们进入代码实操。

2.1 创建

image.png

我们创建了两个函数,并将两个都放在主函数里面执行,我们来看看执行的结果。

image.png

从控制台打印的结果可以看出,我们的两个函数和主函数都是在同一个进程内,接下来我们要进入正题,我们这里要稍微改造一下代码。

image.png

我们创建了一个进程去执行 work_a 函数,我们来看看执行的结果。

image.png

从执行结果来看我们work_a 已经执行在另外一个进程中了,work_b 和 主函数 的 函数id 是一样的,

说明它们实在同一个进程中的。

而我们也发现执行的时间少了一半,因为我们的进程之间是无不干扰的,你跑你的,我跑我的,两个一起跑,这大大提升了我们的执行效率。

image.png

我们现在给 work_b 也 放到一个进程中去,看看执行的效果是怎么样的。

image.png

我们可以看到时间直接打印了,这是为什么呢?

前面我们有说到。进程之间是无不干扰的,然后 name 是主进程,主进程没有了干扰,所以就直接执行了。

2.2 阻塞

如果我们想要让两个

子进程先执行完毕再执行主进程这个就可以使用到join。

我们来优化一下代码。

image.png

再来看看执行效果。

image.png

从执行结果来看,我们确实是实现了先执行完子线程再执行主线程,至于为什么控制台看起来优点乱,是因为有的进程它执行的时间是一致的。重叠在一起了。

3、 进程池和进程锁

由于每个进程都会消耗内存和cpu 资源,所以我们不能无限创建进程,这样有可能会发生系统的死机的情况。

为了解决这个问题,我们可以使用多线程来替代,或者进程池。

还有多进程还存在同时修改一个文件的时候,会出现问题,解决方方法就是给这个文件上一把锁。

3.1 进程池

我们现在知道,进程不能创建太多,太多容易造成系统死机 ,所以我们要固定进程的创建数量,这个时候借助进程池的帮助。

我们可以认为进程池就是个池子,在这个池子创建好一定数量的进程 。

image.png

比如上面这张图中的一个正方形的池子,里面有六个进程,这六个进程会伴随着进程池一起被创建。

我们要知道,普通的进程都要经历创建和关闭,这一建一关都要损耗一定的性能,而进程池中的性能,只需要经历一次创建就能一直往下使用,这也就避免了创建和关闭的性能损耗,伴随着进程池关闭,进程也会随之关闭。

了解了进程池的作用,我们就来了解如何去创建进程池。

函数名

介绍

参数

返回值

Pool

进程池创建

Processcount

进程池创建

apply_async

任务加入进程池(异步)

参数

close

关闭进程池

join

等待进程池任务结束

进入代码实操。

image.png

看看执行效果。

image.png

从执行效果来看,我们可以看到,有五个不同的进程id,这说明我们确实是在进程池创建了五个不同的进程,还有就是进程的执行,并没有按照顺序,这是因为它用了异步的处理方法,谁先干完活,谁就去接新的任务。

上面我们是用了sleep 去阻塞主进程的执行效率。因为如果不阻塞的话,主进程立马就执行完毕并关闭。这样子进程根本没有时间执行。

可不可以不用sleep就能实现子进程执行完再关闭,当然可以,这就可以使用到我们的joinl了,使用join往往伴随着 我们的close。

我们来看看代码:

image.png

执行效果是一样的,需要注意的是,在某些场景中,我们是需要主进程一直启动着,只要有任务进来就执行,这个时候我们就不需要使用close,但如果是那种一次性的脚本任务,就需要使用到close 去关闭主进程了。

接下来我们来看看如何获得进程中的返回值。

image.png

3.2 进程锁

了解完进程池,我们就可以来了解一下进程锁了,其实锁,大家都理解,我们可以给大门上一把锁。

举个栗子,很多人冲向一个厕所,但是厕所只有一个马桶,肯定不能支持这么多人进去,所以第一个人进去之后,就把门锁上了,只有等第一个人解决完之后出来把锁解了,第二个人才能进去,第二个人再把门锁上,后面的以此类推。

了解了进程锁,我们就来看看如果使用进程锁进行加锁与解锁。

函数名

介绍

参数

返回值

acquire

上锁

release

开锁(解锁)

image.png

使用方式还是很简单的,执行效果得大家去试试看了,它会一个一个的执行,而不是像前面五个五个的执行。

4、进程之间的通信

进程之间的通信依赖于队列,所以我们来看看如何创建队列。

我们依然要用到 multiprocessing这个模块。

函数名

介绍

参数

返回值

Queue

队列的创建

mac_count

队列对象

put

信息放入队列

message

get

获取队列信息

str

# coding:utf-8
import time
import json
import multiprocessing
# 声明一个类
class Work(object):
    def __init__(self, q):
        self.q = q  # 初始化,创建队列
    def send(self, message):
        if not isinstance(message, str):
            message = json.dumps(message)
        self.q.put(message)  # 信息放入队列
    def send_all(self):
        for i in range(20):
            self.q.put(i)  # 信息放入队列
            time.sleep(1)
    def receive(self):
        while 1:
            result = self.q.get()  # 获取队列信息
            try:
                res = json.loads(result)
            except:
                res = result
            print('recv is %s' % res)
if __name__ == '__main__':
    q = multiprocessing.Queue()  # 队列
    work = Work(q)  # 实例化类
    send = multiprocessing.Process(target=work.send, args=({'name': '一切总会归于平淡'},))  # 创建线程
    recv = multiprocessing.Process(target=work.receive)  # 创建线程
    send_all_p = multiprocessing.Process(target=work.send_all)  # 创建线程
    send.start()  # 启动线程
    recv.start()  # 启动线程
    send_all_p.start()  # 启动线程
    send_all_p.join()  # 阻塞执行时间最长的线程
    recv.terminate()  # 关闭队列

执行结果:

image.png

这样我们就通过队列实现进程之间的通信了。

5、线程的创建

在python中有很多的多线程模块,其中最常用的就是 -- threading。

函数名

说明

用法

Thread

创建线程

Thread(target,args)

start

启动线程

start()

join

阻塞直到线程执行结束

join(timout=None)

getName

获取线程的名字

getName()

setName

设置线程的名字

setNmae(name)

is_alive

判断线程是否存活

is_alive()

setDaemon

守护线程

setDaemon(True)

看完上面的介绍,其实大家发现,线程中的方法跟我们进程中的大同小异。

接下来我们看代码演示。


image.png

现在我们还没有用到多线程,执行时间是10秒,接下来我们创建线程去提高我们代码执行的效率。

image.png

我们再看看执行效果。

image.png

哇,只花了一秒就执行完毕了。

6、线程池的创建

线程池和进程池的原理是相同的,这里就不再给大家做解释了。

我们使用Python 的配置包 -- concurrent 来帮助我们完成创建下线程池的任务。

方法名

说明

举例

futures.ThreadPoolExecutor

创建线程池

tpool = ThreadPoolExecutor(max_workers)

submit

往线程池中加入任务

submit(target,args)

done

线程池中的某个线程是否完成了任务

done()

result

获取当前线程执行任务的结果

result()

上代码

image.png

7、异步

要了解异步,我们就要只要什么是同步。

平常我们的代码是从上往下执行的,就像 1,2,3,4 ......,2要等1 执行完才能轮到2 后面的也都一样,如果其中一个要执行的特别久就容易发生阻塞。

而异步不需要这样,2不需要等1执行2完,它就可以进入执行状态,而且就算其中有一个发生了阻塞,后面的也不会受到影响,听来是不是优点类似与多进程和多线程?

确实如此,异步和多进程和多线程它们类似于兄弟,让我们看看它们之间有何相同有何不同。

首先我们要知道,异步实际上也是一种线程。只不过它是一种比较轻量级的线程,我们将其称为 ‘协程’;所以协程也是进程下的一部分,但和多线程,多进程不同的是,多线程和多进程不能获取函数的返回值,但是异步可以获取。

7.1 async 与 await 关键字

名字

说明

用法

async

定义异步

async def  方法名():

await

执行异步

async def 方法名():  retult = await 方法名()

注意 :

使用await,方法必须被 async 定义。

这里有一个问题,我们知道最上层的代码一定不是个函数,它无法定义async,例如我们的主程序。

image.png

这里我们要借助一个帮手,asyncio,这个帮手它有太多使用异步的方法,这篇就只介绍两种。

函数名

介绍

参数

返回值

gather

将异步函数批量执行

asyncfunc

List 函数的返回值

run

执行主导异步函数

[task]

执行函数的返回结果

image.png

看看执行结果:

image.png

可以看我们确实是实现了异步操作,而它们都是在同一个进程。

2、gevent

这个模块是需要下载的。

pip install gevent

函数名

介绍

参数

返回值

spawn

创建协程对象

Func,args

协程对象

joinall

批量处理协程对象

[spawnobj]

[spawnobj]

image.png

执行效果:

image.png

Python 进程与线程编程.md

Python 进程与线程编程.pdf

目录
相关文章
|
17天前
|
人工智能 数据可视化 数据挖掘
探索Python编程:从基础到高级
在这篇文章中,我们将一起深入探索Python编程的世界。无论你是初学者还是有经验的程序员,都可以从中获得新的知识和技能。我们将从Python的基础语法开始,然后逐步过渡到更复杂的主题,如面向对象编程、异常处理和模块使用。最后,我们将通过一些实际的代码示例,来展示如何应用这些知识解决实际问题。让我们一起开启Python编程的旅程吧!
|
16天前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
4天前
|
Unix Linux 程序员
[oeasy]python053_学编程为什么从hello_world_开始
视频介绍了“Hello World”程序的由来及其在编程中的重要性。从贝尔实验室诞生的Unix系统和C语言说起,讲述了“Hello World”作为经典示例的起源和流传过程。文章还探讨了C语言对其他编程语言的影响,以及它在系统编程中的地位。最后总结了“Hello World”、print、小括号和双引号等编程概念的来源。
98 80
|
4天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
44 13
|
3天前
|
分布式计算 大数据 数据处理
技术评测:MaxCompute MaxFrame——阿里云自研分布式计算框架的Python编程接口
随着大数据和人工智能技术的发展,数据处理的需求日益增长。阿里云推出的MaxCompute MaxFrame(简称“MaxFrame”)是一个专为Python开发者设计的分布式计算框架,它不仅支持Python编程接口,还能直接利用MaxCompute的云原生大数据计算资源和服务。本文将通过一系列最佳实践测评,探讨MaxFrame在分布式Pandas处理以及大语言模型数据处理场景中的表现,并分析其在实际工作中的应用潜力。
17 2
|
16天前
|
小程序 开发者 Python
探索Python编程:从基础到实战
本文将引导你走进Python编程的世界,从基础语法开始,逐步深入到实战项目。我们将一起探讨如何在编程中发挥创意,解决问题,并分享一些实用的技巧和心得。无论你是编程新手还是有一定经验的开发者,这篇文章都将为你提供有价值的参考。让我们一起开启Python编程的探索之旅吧!
41 10
|
17天前
|
IDE 程序员 开发工具
Python编程入门:打造你的第一个程序
迈出编程的第一步,就像在未知的海洋中航行。本文是你启航的指南针,带你了解Python这门语言的魅力所在,并手把手教你构建第一个属于自己的程序。从安装环境到编写代码,我们将一步步走过这段旅程。准备好了吗?让我们开始吧!
|
16天前
|
安全 算法 Java
Java多线程编程中的陷阱与最佳实践####
本文探讨了Java多线程编程中常见的陷阱,并介绍了如何通过最佳实践来避免这些问题。我们将从基础概念入手,逐步深入到具体的代码示例,帮助开发者更好地理解和应用多线程技术。无论是初学者还是有经验的开发者,都能从中获得有价值的见解和建议。 ####
|
18天前
|
关系型数据库 开发者 Python
Python编程中的面向对象设计原则####
在本文中,我们将探讨Python编程中的面向对象设计原则。面向对象编程(OOP)是一种通过使用“对象”和“类”的概念来组织代码的方法。我们将介绍SOLID原则,包括单一职责原则、开放/封闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。这些原则有助于提高代码的可读性、可维护性和可扩展性。 ####
|
16天前
|
Java 调度
Java中的多线程编程与并发控制
本文深入探讨了Java编程语言中多线程编程的基础知识和并发控制机制。文章首先介绍了多线程的基本概念,包括线程的定义、生命周期以及在Java中创建和管理线程的方法。接着,详细讲解了Java提供的同步机制,如synchronized关键字、wait()和notify()方法等,以及如何通过这些机制实现线程间的协调与通信。最后,本文还讨论了一些常见的并发问题,例如死锁、竞态条件等,并提供了相应的解决策略。
40 3
下一篇
DataWorks