进程

首先,先从多任务讲起:
现代操作系统(Windows、Mac OS X、Linux、UNIX等)都支持"多任务"
什么叫多任务???
操作系统同时可以运行多个任务

早期电脑都是单核cpu,他执行任务原理:
操作系统轮流让各个任务交替执行,QQ执行2Us,切换到微信,执行2Us,
再切换到陌陌,执行2Us,……。表面上看,每个任务反复执行下去,但是CPU调度
执行太快了,导致我们感觉就像所有任务都在同时执行一样。

现在是多核CPU实现多任务原理:
真正的并行执行多任务只能在多核CPU上实现,但是由于任务数量远远多于CPU核心数量
所以,操作系统也会自动把很多任务轮流调度到每个核心上的执行

并发:看上去一起执行,任务数多于核心数
并行:真正一起执行,任务数小于等于CPU核心数

实现多任务的方式:
1、多进程模式
2、多线程模式(常用)
3、协程模式(在开发中,很少用)
4、多进程+多线程 模式
接下来讲讲进程:
任务管理器:里面都是进程
对于操作系统而言,一个任务就是一个进程
进程是系统中程序执行和资源分配的基本单位,每个进程都有自己的数据段(存储数据),
代码段(存储代码)、和堆(存储一些对象的)栈(普通的变量就在栈上)段。

进程的目的:实现多任务,提高我们的执行效率
     进程: 就是创建一个任务,让它去执行其他的功能

===============================================================================

from time import sleep


def run():
    while True:
        print("sunck is a nice man")
        sleep(1.2)


if __name__ == '__main__':
    while True:
        print("sunck is a good man")
        sleep(1)


    # 不会执行 run 方法,只有上面的while循环结束才可以执行
    # 要让这个两个任务同时执行,就是多任务
    run()

运行结果:
sunck is a good man
sunck is a good man
sunck is a good man
sunck is a good man
sunck is a good man
sunck is a good man

===============================================================================

multiprocessing 库
multiple: adj.数量多的;多种多样的;
            n.倍数;
processing: v.处理;加工;
            n.过程;加工处理;处置;进行;
            adj.经过特殊加工的;(用化学方法等)处理过的;

在linux下可以使用C语言的方法fork实现多进程,但是它不支持window,
但是这个三方库multiprocessing库是一个跨平台版本的多进程模块
提供了一个Process类来代表一个进程对象

所以我们要使用多进程就要引入multiprocessing库


import os
from multiprocessing import Process
from time import sleep


# 子进程需要执行的代码
def run(adj):
    # os.getpid() 获取当前进程ID号
    # os.getppid() 获取当前进程的父进程ID号
    while True:
        print("sunck is a %s man--%s--%s"%(adj, os.getpid(),os.getppid()))
        sleep(1.2)


if __name__ == '__main__':
    print("主(父)进程启动")
    # os.getpid() 获取当前父进程ID号
    print(os.getpid())

    # 创建一个子进程(在父进程下创建一个进程,故称为该进程的子进程)
    p = Process(target=run, args=("nice",))
    # target:说明 该子进程要执行的任务、代码、函数
    # args:可以给target的函数传参数,是一个元组类型,单个参数要加逗号,

    # 启动进程
    p.start()

    while True:
        print("sunck is a good man")
        sleep(1)
运行结果:
主(父)进程启动
1975
sunck is a good man
sunck is a nice man--1976--1975
sunck is a good man
sunck is a nice man--1976--1975

===============================================================================

'''全局变量在多个进程中是不能共享的'''

from multiprocessing import Process
from time import sleep


NUM = 100


def run():
    print("子进程开始")
    global NUM
    NUM += 1
    print(NUM)
    print("子进程结束")

if __name__ == '__main__':
    print("父进程开始")
    
    
    p = Process(target=run)
    p.start()
    p.join()
    
    print(NUM)
    # 在子进程中修改全局变量对父进程中的全局变量没有影响
    # 为什么没影响呢?因为他在创建子进程时,对全局变量做了一个备份,父进程中的与子进程中的
    # NUM是两个完全不同的变量
    print("父进程结束--%d" % NUM)

运行结果:
父进程开始
子进程开始
101
子进程结束
100
父进程结束--100
# 父子进程的先后执行顺序

from multiprocessing import Process
from time import sleep

def run(args):
    print("子进程启动")
    sleep(3)
    print("子进程结束")

if __name__ == '__main__':
    print("主(父)进程启动")

    p = Process(target=run, args=("nice",))
    p.start()

    # 父进程的结束不能影响子进程,让父进程等待子进程,再执行父进程
    p.join()

    print("父进程结束")

 

'''
进程池
'''

import os
import time
import random

# 为了对多个进程好管理,使用进程池
# from multiprocessing import Process
from multiprocessing import Pool


def run(name):
    print('子进程%s启动--%s' % (name, os.getpid()))
    strat = time.time()
    time.sleep(random.choice([1, 2, 3]))
    end = time.time()
    print('子进程%s结束--%s--耗时%.2f' % (name, os.getpid(), end-strat))


if __name__ == '__main__':
    print('父进程启动')

    # 创建多个进程
    # 进程池
    # 4:表示可以同时执行的进程数量
    # 参数可以写,pool默认大小是CPU核心数
    pp = Pool(4)

    # 创建进程,创建的进程数要大于CPU核心数,这样才能体验到多进程的效果
    # 这里因为进程都是干一样的活,所以使用for循环创建进程
    # 子进程的执行数据是没有顺序的。
    for i in range(5):
        # 创建进程,放进进程池,统一管理
        pp.apply_async(run, args=(i,))

    '''
    如果每个进程干的活不一样,那就单独创建每一个进程,不要写for循环。
    例:
    pp.apply_async(func1, agrs=())
    pp.apply_async(func2, agrs=())
    pp.apply_async(func3, agrs=())
    pp.apply_async(func4, agrs=())
    pp.apply_async(func5, agrs=())
    '''

    # 在调用join之前,必须先调用close,并且在调用close之后,就不能再继续添加新的进程了
    pp.close()
    # 进程池对象调用的join,会等待进程池中的所有的子进程结束完毕,再去执行父进程。
    pp.join()

    print("父进程结束")

'''
运行结果:  这里进程看似0,1,2,3启动的,实际上,进程启动是没有顺序的。
父进程启动
子进程0启动--5251
子进程1启动--5252
子进程2启动--5253
子进程3启动--5254
子进程2结束--5253--耗时1.00
子进程0结束--5251--耗时1.00
子进程4启动--5253
子进程3结束--5254--耗时1.00
子进程1结束--5252--耗时2.00
子进程4结束--5253--耗时3.00
父进程结束
'''
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# 多进程实现文件拷贝

import os
import time

from multiprocessing import Pool


# 实现文件的拷贝
def copy_file(read_file_path, write_file_path):
    read_file = open(read_file_path, 'rb')
    write_file = open(write_file_path, 'wb')
    context = read_file.read()
    write_file.write(context)
    read_file.close()
    write_file.close()


path = r''
to_path = r''

if __name__ == '__main__':
    # 读取path下的所有文件
    file_list = os.listdir(path)

    start = time.time()
    pp = Pool(2)
    for file_name in file_list:
        pp.apply_async(copy_file,
                       args=(os.path.join(path, file_name),
                             os.path.join(to_path, file_name)
                             )
                       )
        pp.close()
        pp.join()
        end = time.time()
        run_time = end - start
        print('总耗时---%d' % run_time)

 

#二次封装的文件名,一般是:自己的名字+第三方库的名称

import os
import time
from multiprocessing import Process


class SunckProcess(Process):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        super().run()
        print('子进程(%s-%s)启动' % (self.name, os.getpid()))
        # 子进程的功能
        time.sleep(3)
        print('子进程(%s-%s)结束' % (self.name, os.getpid()))

==================================================================

from sunckProcess import SunckProcess


if __name__ == '__main__':
    print('父进程启动')

    # 创建子进程
    p = SunckProcess('test')
    # 在这里不要调用进程里面的run方法,调用它的start就会自动调用进程对象的run方法
    p.start()
    p.join()

    print("父进程结束")

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章