天天看点

Python进程池及自定义进程Python进程池及自定义进程

Python进程池及自定义进程

微信关注公众号:夜寒信息

致力于为每一位用户免费提供更优质技术帮助与资源供给,感谢支持!

  这次给大家分享Python的进程池及自定义进程,由于Python基础已经讲述,不再赘述类,方法,及其他基础语法的概念。多进程在任务的执行使用非常广泛,比如Windows可以同时开很多的窗口,QQ,微信,游戏等。以后我们也会讲解多线程,多线程常用于下载,以后会有讲解。

一、进程重写

  首先我们按照常规导入multiprocessing模块,同样我们使用

from multiprocessing import Process

语句来导入Process类。还记得上篇文章写的run()方法吗(Python的多进程运行)要重写进程,就要重写run()方法。

  如果我们我们要自定义一个进程,那么我们就需要在创建我们自己的类时继承父类的Process方法:

class MyProcess(Process):
	def run(self):
		pass
           

  这样我们便完成了进程自定义的结构,Process父类的东西都可以在我们的自定义进程内使用。我们可以使用一个例子,来给大家讲解。

  假设我们创建两个进程,循环打印所传入的参数并计数,每执行一次进程加一,我们所需要实现的代码如下:

class MyProcess(Process):
    def run(self):
        n = 1
        while True:
            print('进程名:{} n的值:{}'.format(self.name, n))
            n += 1
           

  每当我们使用start()方法时,系统都会先进入Process类中找run()方法,通过run()方法来启动进程。我们再来添加一个主函数,创建两个进程对象,并将他们添加到进程中:

if __name__ == '__main__':
    p1 = MyProcess(name='李诺')
    p2 = MyProcess(name='夜寒')
    p1.start()
    p2.start()
           

  这是我们运行程序,变发现程序按照我们的需求进行。下附完整代码:

# 进程:自定义
from multiprocessing import Process


class MyProcess(Process):
    # 重写run()方法

    def run(self):
        n = 1
        while True:
            print('进程名:{} n的值:{}'.format(self.name, n))
            n += 1


if __name__ == '__main__':
    p1 = MyProcess(name='李诺')
    p2 = MyProcess(name='夜寒')
    p1.start()
    p2.start()
           

二、进程池

  下面我们进程池,当我们需要创建成百上千的进程时,仅仅手动创建则会非常麻烦,于是我们来使用进程池。我们使用

from multiprocessing import Pool

来调用进程池,使用

Pool()

方法来创建进程池,并定义最大进程数。进程池分为阻塞式和非阻塞式,我们一一讲解。

一、非阻塞式进程池

首先我们需要导入这几个库:

import os
import time
from multiprocessing import Pool
from random import random
           

  首先我们创建一个任务。我们先传入一个任务名,我们使用random和sleep方法来模拟做任务的时间,再使用time来获得做任务的耗时使用os库来获得人物的pid和ppid。最后再返回我们做任务的结果,以下是实现的代码:

def task(task_name):
    start = time.time()
    time.sleep(random() * 2)
    end = time.time()
    return '完成{},用时:{},进程ID:{}'.format(task_name, (end-start), os.getpid())
           

  接下来我们再创建主函数,先创建进程池,再创建一个列表,里面添加自己所需的进程。我们使用

pool.apply_async()

来将进程添加到进程池,下面附上实现代码:

if __name__ == '__main__':
    pool = Pool(5)
    tasks = ['听音乐', '打游戏', '洗衣服', '去散步', '去学习', '上厕所', '打代码']
    for i in tasks:
        pool.apply_async(task, args=(i,), callback=call_back)

    pool.close()
    pool.join()
    print('OVER')
           

  其中,pool.close()是表示添加任务结束,需要在添加完任务后在主进程加入此语句。进程池的运行必须要添加pool,join()方法,它可以堵住主进程,使进程池的任务全部执行完成之后才能结束主进程。进程池的运行依赖于主进程,主进程运行完进程池内的任务便会结束,所以添加pool.join(),否则添加完任务后不运行便会结束。

  我们再来了解回调方法

callback

它会将进程(

task()

)的返回值接收,并传入回调函数,回调函数再进行处理。我们定义一个call_back()函数,用来充当callback的参数,实现代码如下:

def call_back(n):
    print(n)
           

  回调函数必须传入参数(上述代码中

n

)我们打印n的值也就是task()的返回值。以下是全部代码:

# 非阻塞式:全部添加到队列中,立即返回,并未等待其他进程执行完毕,但是回调函数等待任务完成后才调用
# 进程池
import os
import time
from multiprocessing import Pool
from random import random


# 非阻塞式进程
def task(task_name):
    # print('开始任务:', task_name)
    start = time.time()
    time.sleep(random() * 2)
    end = time.time()
    return '完成{},用时:{},进程ID:{}'.format(task_name, (end-start), os.getpid())


def call_back(n):
    print(n)


if __name__ == '__main__':
    pool = Pool(5)
    tasks = ['听音乐', '打游戏', '洗衣服', '去散步', '去学习', '上厕所', '打代码']
    for i in tasks:
        pool.apply_async(task, args=(i,), callback=call_back)

    pool.close()    # 添加表示任务结束
    pool.join()     # 堵住主进程,完成任务之后可继续执行主进程
    print('OVER')
           

下面是执行截图:

Python进程池及自定义进程Python进程池及自定义进程

  我们添加了七个任务,但进程池只有5个空位。于是系统在添加进程时,未被添加的任务会等待,当其他任务执行完有空位后它在被添加。其中,系统在执行任务时,会从进程池中同时随机选取任务执行,可以看任务名称,不是按列表顺序执行,这便是非阻塞式进程池。

一、非阻塞式进程池

  阻塞式进程池只需将

pool.apply_async()

改为

pool.apply()

即可。其中,系统在执行任务时,会按序从进程池中选取任务执行,可以看任务名称,当第一个任务未执行完时下一个任务不会被执行。这样虽然不会造成任务执行不按序而冲突,但会大大加长任务的执行时间,效率低下。以下附上实现需求的所有代码,这便是阻塞式进程池。

'''
 特点:
 添加一个任务执行一个任务,如果一个任务不结束,另一个任务就进不来

 进程池:
 pool = Pool(max)   创建进程池对象
 pool.apply()       阻塞的
 pool.apply_async() 非阻塞的

 pool.close()   执行结束后关闭进程
 pool.join()    让主进程让步
'''

import os
import time
from multiprocessing import Pool
from random import random


# 非阻塞式进程
def task(task_name):
    # print('开始任务:', task_name)
    start = time.time()
    time.sleep(random() * 2)
    end = time.time()
    print('完成{},用时:{},进程ID:{}'.format(task_name, (end-start), os.getpid()))


def call_back(n):
    print(n)


if __name__ == '__main__':
    pool = Pool(5)
    tasks = ['听音乐', '打游戏', '洗衣服', '去散步', '去学习', '上厕所', '打代码']
    for i in tasks:
        pool.apply(task, args=(i,))

    pool.close()    # 添加表示任务结束
    pool.join()     # 堵住主进程,完成任务之后可继续执行主进程
    print('OVER')
           

下面是执行截图:

Python进程池及自定义进程Python进程池及自定义进程

若有问题请关注微信公众号"夜寒信息"

  

微信关注公众号:夜寒信息

致力于为每一位用户免费提供更优质技术帮助与资源供给,感谢支持!