一篇文章让你学会python进程

一.操作系统

  1. 为什么要有操作系统?

计算机是由一个或者多个处理器CPU,内存条,磁盘,键盘,鼠标,显示器,以及各种其他输入输出设备组成的机器。如果我们想让自己的应用程序运行在计算机上,我们需要了解

计算机中所有的细节例如处理器怎么运行,内存的分配等等。每位程序员不可能掌握所有系统实现的细节,并且管理优化这些部件是一件挑战性极强的工作。因此就出现了操作系统(操作系统也是一个软件)。

操作系统的定义:操作系统是一个用来协调、管理和控制计算机硬件和软件资源的系统程序,它位于硬件和应用程序之间。起承上启下的作用。我们写好的程序只需要给操作系统即可,

操作系统会给我们的程序分配内存等等一些操作。

 

二.多任务

多任务就是同一时刻多个任务同时执行,例如开演唱会时明星一边唱歌一边跳舞,开车时眼睛看路手操作方向盘。这些都是多任务场景。

对于电脑来说多任务就是同时运行多个应用程序,例如qq、微信、浏览器等等同时在电脑上运行。

  1. 电脑实现多任务的原理

例如qq、微信、网易云音乐播放器3个应用程序能同时运行是因为CPU在多个应用程序之间高速切换的结果,当CPU切换到了qq,就用0.01s时间(时间不确定)执行qq程序,然后再随机切换到其他应用程序在执行一段时间,CPU在多个程序之间快速往复执行,我们的肉眼根本感觉不到卡顿,导致我们的错觉感觉是同时运行的效果。如果电脑运行了多个程序有时候会出现卡顿现象是因为cup切换不过来了。

2.单核、双核CPU介绍:

单核CPU 指的是CPU中有一个核心(形象理解CPU是人的头,核心是头里面包含的大脑),用来处理程序。

双核/四核CPU 就是CPU中有2个或者4个核心,(1个脑袋中长了2个大脑或者4个大脑),相当于有2个单核CPU或者是4个单核CPU

3.查看CPU:

电脑-->属性-->设备管理器-->处理器,有4个表示一个CPU中有4个核心。

 

 

2.30GHz 表示运算速度,越高越好。例如1s中可以计算多少次。

 

4.在python中实现多任务有3种方式,进程、线程、协程。

 

 

三.进程

  1. 什么是进程

我们想通过酷我听歌,具体的过程应该是先找到酷我应用程序,然后双击就会播放音乐。

当我们双击的时候,操作系统将程序装载到内存中,操作系统为它分配资源,然后才能运行。运行起来的应用程序就称之为进程。也就是说当程序不运行的时候我们称之为程序,当程序运行起来他就是一个进程。通俗的理解就是不运行的时候是程序,运行起来就是进程。程序和进程的对应关系是:程序只有一个,但是进程可以有多个。

例如: 我们可以打开多个QQ

 

    2.创建多进程

  • 不使用多进程实现控制台先打印唱歌,再打印跳舞
import time


def sing():
    # 唱歌3秒
    for i in range(3):
        print('正在唱歌。。。')
        time.sleep(1)


def dance():
    # 跳舞3秒
    for i in range(3):
        print('正在跳舞。。。')
        time.sleep(1)


if __name__ == '__main__':  # 程序执行的入口

    sing()
    dance()

程序运行花费了6s 的时间

 

  • 使用进程让唱歌跳舞一起执行
import time
import multiprocessing


def sing():
    # 唱歌3秒
    for i in range(3):
        print('正在唱歌。。。')
        time.sleep(1)


def dance():
    # 跳舞3秒
    for i in range(3):
        print('正在跳舞。。。')
        time.sleep(1)


def main():
    m1 = multiprocessing.Process(target=sing)   # 创建m1 进程,执行sing()函数
    m2 = multiprocessing.Process(target=dance)  # 创建m2 进程,执行dance()函数
    m1.start()  # 开始执行进程m1
    m2.start()  # 开始执行进程m2

    # 开启了两个子进程,m1和m2


if __name__ == '__main__':  # 程序执行的入口

    main()

运行结果:   正在唱歌。。。
                     正在跳舞。。。
                     正在唱歌。。。
                     正在跳舞。。。
                     正在唱歌。。。
                     正在跳舞。。。

花了3s时间,提高了程序的运行效率

 

程序理解:

主进程从main()开始执行,执行main函数体,当执行到p1.start()时,创建一个子进程,p1子进程中的代码和主进程相同,只是程序执行的开始是 sing函数体。

主进程执行到p2.start()时,同样复制一份主进程代码从danc函数体开始执行。

使用进程方式实现多任务耗费的资源比较大,因为一个进程就需要使用一份系统资源。

 

 

3.进程的状态

在程序运行的过程中,由于被操作系统的调度算法控制,程序会进入几个状态:就绪,运行和阻塞。

 

(1)就绪状态

当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态。

(2)执行/运行(Running)状态

当进程已获得处理机,其程序正在处理机上执行,此时的进程状态称为执行状态。

(3)阻塞(Blocked)状态

正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。引起进程阻塞的事件可有多种,例如,等待I/O完成、申请缓冲区不能满足、等待信件(信号)等。

 

 

4. 进程之间的 通讯

刚才我们说了进程可以理解为复制了一份程序有加载到了内存了,进程之间是独立的,如果我想两个进程之间进行通讯怎么办呢?我们可以使用Queue 队列,队列是一种先进先出的存储数据结构,就比如排队上厕所一个道理。

两个进程通讯,就是一个子进程往queue中写内容,另一个进程从queue中取出数据。就实现了进程间的通讯了。

 

queue队列

(1)q = multiprocessing.Queue(3)  # 3表示只能存放3个数据

参数 :maxsize是队列中允许的最大项数。如果省略此参数,则无大小限制。

返回值q 是队列对象

(2)put()方法 ,向队列中存放数据。如果队列已满,此方法将阻塞至有空间可用为止。

(3)get()返回q中的一个项目。如果q为空,此方法将阻塞,直到队列中有项目可用为止。

(4)get_nowait(): 不等待,直接抛出异常

(5)full()如果q已满,返回为True

(6)q.empty() 如果调用此方法时 q为空,返回True。

 

put()和get()

get_nowait()

full()

empty()

 

练习1:使用queue模拟多任务下载和处理数据

from multiprocessing import Process, Queue


def download_data(q):
    lst = ['a', 'b', 'c']
    for i in lst:
        q.put(i)  # 将下载的数据保存到队列中
    print('数据下载完了。。。')


def process_data(q):
    for i in range(q.qsize()):
        print(q.get())

    print('数据处理完了。。。')


def main():
    q = Queue()  # 创建一个队列
    # 创建两个子进程
    q1 = Process(target=download_data, args=(q,))
    q2 = Process(target=process_data, args=(q,))
    q1.start()
    q2.start()


if __name__ == '__main__':
    main()

 

5.进程池

当需要创建的子进程数量不多时,我们可以直接利用multiporcessing中的Process动态生成多个进程,但是如果现在有100个任务需要处理,那我们需要多少个子进程呢,如果我们创建100个子进程也可以实现,但是资源比较浪费。我们也可以创建指定个数个子进程,例如只创建10个子进程,让着10个子进程重复的执行任务,这样就节约了资源。

就比如我们去景区湖上游玩,游船是重复利用的。

我们可以使用multiprocessing模块提供的Pool类,也就是进程池,可以达到进程重复利用。

创建进程池对象的时候可以指定一个最大进程数,当有新的请求提交到进程池中,如果池中的进程数还没有满,那么就会创建一个新的进程用来执行该请求,但是如果池中的进程数满了,该请求就会等待,直到进程池中的进程有结束的了,才会使用这个结束的进程来执行新的任务。

 

join 主进程等待所有子进程执行完毕,必须在close之后。

close 等待所有进程结束才关闭线程池

from multiprocessing import Process, Pool
import time


def foo(i):
    print('i的值是---》', i)
    time.sleep(2)
    print('end...')


if __name__ == '__main__':

    pool = Pool(3)  # 创建进程池对象

    for i in range(10):
        pool.apply_async(func=foo, args=(i,))  # 将任务添加到进程池中

    pool.close()  # 关闭进程池
    pool.join()  # 主进程等待所有子进程执行完毕后主进程才往下执行,必须在close后面

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值