Python中的进程池和线程池

0.concurrent.futures库

参考:https://docs.python.org/3/library/concurrent.futures.html

之前我们使用多线程(threading)和多进程(multiprocessing)完成常规的需求:
    在启动的时候start、jon等步骤不能省,复杂的需要还要用1-2个队列。
    随着需求越来越复杂,如果没有良好的设计和抽象这部分的功能层次,代码量越多调试的难度就越大。
    有没有什么好的方法把这些步骤抽象一下呢,让我们不关注这些细节,轻装上阵呢?

答案是:有的,
从Python3.2开始一个叫做concurrent.futures被纳入了标准库;
而在Python2它属于第三方的futures库,需要手动安装: pip install futures

The concurrent.futures module provides a high-level interface for asynchronously executing callables.

The asynchronous execution can be be performed by threads using ThreadPoolExecutor
or seperate processes using ProcessPoolExecutor. Both implement the same interface,
which is defined by the abstract Executor class.

1.进程池

  - 串行执行的情况:

import math,time

PRIMES = [
    112272535095293,
    112582705942171,
    112272535095293,
    115280095190773,
    115797848077099,
    1099726899285419]
def is_prime(n):
    if n % 2 == 0:
        return False
    sqrt_n = int(math.floor(math.sqrt(n)))
    for i in range(3, sqrt_n + 1, 2):
        if n % i == 0:
            return False
    return True
def main():
    for num in PRIMES:
        print(‘%d is prime: %s‘ % (num, is_prime(num)))

if __name__ == ‘__main__‘:
    start_time = time.time()
    main()
    end_time = time.time()
    print(‘Run time is %s‘ % (end_time-start_time))

---结果---
112272535095293 is prime: True
112582705942171 is prime: True
112272535095293 is prime: True
115280095190773 is prime: True
115797848077099 is prime: True
1099726899285419 is prime: False
Run time is 3.9570000171661377

  - 使用multiprocessing.Pool的情况:

import math,time
from multiprocessing import Pool

PRIMES = [
    112272535095293,
    112582705942171,
    112272535095293,
    115280095190773,
    115797848077099,
    1099726899285419]
def is_prime(n):
    if n % 2 == 0:
        return False
    sqrt_n = int(math.floor(math.sqrt(n)))
    for i in range(3, sqrt_n + 1, 2):
        if n % i == 0:
            return False
    return True
def main():
    pool = Pool()
    res_l = []
    for prime in PRIMES:
        res = pool.apply_async(func=is_prime,args=(prime,))
        res_l.append(res)
    pool.close()
    pool.join()
    for number, prime in zip(PRIMES, res_l):
        print(‘%d is prime: %s‘ % (number, prime.get()))

if __name__ == ‘__main__‘:
    start_time = time.time()
    main()
    end_time = time.time()
    print(‘Run time is %s‘ % (end_time-start_time))

---结果---
112272535095293 is prime: True
112582705942171 is prime: True
112272535095293 is prime: True
115280095190773 is prime: True
115797848077099 is prime: True
1099726899285419 is prime: False
Run time is 2.687000036239624

  - 使用进程池 concurrent.futures.ProcessPoolExecutor的情况:

    - 参考:http://pythonhosted.org/futures/#concurrent.futures.ProcessPoolExecutor

ProcessPoolExecutor uses the multiprocessing module,
which allows it to side-step the Global Interpreter Lock
but also means that only picklable objects can be executed and returned.

class concurrent.futures.ProcessPoolExecutor(max_workers=None)
    Executes calls asynchronously using a pool of at most max_workers processes.
    If max_workers is None or not given then as many worker processes will be created as the machine has processors.

    - ProcessPoolExecutor 本质上也是调用multiprocessing模块

import math,time
from concurrent import futures

PRIMES = [
    112272535095293,
    112582705942171,
    112272535095293,
    115280095190773,
    115797848077099,
    1099726899285419]
def is_prime(n):
    if n % 2 == 0:
        return False
    sqrt_n = int(math.floor(math.sqrt(n)))
    for i in range(3, sqrt_n + 1, 2):
        if n % i == 0:
            return False
    return True
def main():
    with futures.ProcessPoolExecutor() as executor:
        for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
            print(‘%d is prime: %s‘ % (number, prime))

if __name__ == ‘__main__‘:
    start_time = time.time()
    main()
    end_time = time.time()
    print(‘Run time is %s‘ % (end_time-start_time))

---结果---
112272535095293 is prime: True
112582705942171 is prime: True
112272535095293 is prime: True
115280095190773 is prime: True
115797848077099 is prime: True
1099726899285419 is prime: False
Run time is 2.482999801635742

2.线程池

  - 参考:http://pythonhosted.org/futures/#threadpoolexecutor-objects

The ThreadPoolExecutor class is an Executor subclass that uses a pool of threads to execute calls asynchronously.

class concurrent.futures.ThreadPoolExecutor(max_workers)
    Executes calls asynchronously using at pool of at most max_workers threads.

  - 串行执行的情况:

import urllib.request
import time

URLS = [
    ‘http://www.foxnews.com/‘,
    ‘https://www.stanford.edu/‘,
    ‘http://www.mit.edu/‘,
    ‘https://www.python.org/‘,
    ‘https://www.yahoo.com/‘,
    ‘http://www.ox.ac.uk/‘
]

def load_url(url, timeout):
    return urllib.request.urlopen(url, timeout=timeout).read()

start_time = time.time()
for url in URLS:
    print(‘%r page is %d bytes‘ % (url, len(load_url(url,60))))
end_time = time.time()
print("Run time is %s" % (end_time-start_time))

---结果---
‘http://www.foxnews.com/‘ page is 71131 bytes
‘https://www.stanford.edu/‘ page is 68595 bytes
‘http://www.mit.edu/‘ page is 21405 bytes
‘https://www.python.org/‘ page is 47701 bytes
‘https://www.yahoo.com/‘ page is 434510 bytes
‘http://www.ox.ac.uk/‘ page is 93411 bytes
Run time is 5.068000078201294

  - 使用多线程的情况:

import urllib.request
import time
from threading import Thread

URLS = [
    ‘http://www.foxnews.com/‘,
    ‘https://www.stanford.edu/‘,
    ‘http://www.mit.edu/‘,
    ‘https://www.python.org/‘,
    ‘https://www.yahoo.com/‘,
    ‘http://www.ox.ac.uk/‘
]
def load_url(url, timeout):
    res = urllib.request.urlopen(url, timeout=timeout).read()
    print(‘%r page is %d bytes‘ % (url, len(res)))
t_l = []
start_time = time.time()
for url in URLS:
    t = Thread(target=load_url,args=(url,60,))
    t_l.append(t)
    t.start()
for t in t_l:
    t.join()
end_time = time.time()
print("Run time is %s" % (end_time-start_time))

---结果---
‘http://www.mit.edu/‘ page is 21403 bytes
‘http://www.foxnews.com/‘ page is 71735 bytes
‘https://www.python.org/‘ page is 47701 bytes
‘https://www.stanford.edu/‘ page is 69130 bytes
‘http://www.ox.ac.uk/‘ page is 93411 bytes
‘https://www.yahoo.com/‘ page is 446715 bytes
Run time is 2.6540000438690186

  - 使用线程池 concurrent.futures.ThreadPoolExecutor的情况:

from concurrent import futures
import urllib.request
import time

URLS = [
    ‘http://www.foxnews.com/‘,
    ‘https://www.stanford.edu/‘,
    ‘http://www.mit.edu/‘,
    ‘https://www.python.org/‘,
    ‘https://www.yahoo.com/‘,
    ‘http://www.ox.ac.uk/‘
]

def load_url(url, timeout):
    return urllib.request.urlopen(url, timeout=timeout).read()

start_time = time.time()
with futures.ThreadPoolExecutor(max_workers=5) as executor:
    future_to_url = dict((executor.submit(load_url, url, 60), url) for url in URLS)
    for future in futures.as_completed(future_to_url):
        url = future_to_url[future]
        if future.exception() is not None:
            print(‘%r generated an exception: %s‘ % (url,future.exception()))
        else:
            print(‘%r page is %d bytes‘ % (url, len(future.result())))
end_time = time.time()
print("Run time is %s" % (end_time-start_time))

---结果---
‘http://www.mit.edu/‘ page is 21405 bytes
‘http://www.foxnews.com/‘ page is 71197 bytes
‘https://www.python.org/‘ page is 47701 bytes
‘http://www.ox.ac.uk/‘ page is 93411 bytes
‘https://www.yahoo.com/‘ page is 444854 bytes
‘https://www.stanford.edu/‘ page is 68595 bytes
Run time is 2.497999906539917

  

备注:由于网络不稳定因素,所以Run time仅作为参考值;

时间: 2024-08-15 01:54:19

Python中的进程池和线程池的相关文章

4月27日 python学习总结 GIL、进程池、线程池、同步、异步、阻塞、非阻塞

一.GIL:全局解释器锁 1 .GIL:全局解释器锁 GIL本质就是一把互斥锁,是夹在解释器身上的, 同一个进程内的所有线程都需要先抢到GIL锁,才能执行解释器代码 2.GIL的优缺点: 优点:  保证Cpython解释器内存管理的线程安全 缺点:同一进程内所有的线程同一时刻只能有一个执行,也就说Cpython解释器的多线程无法实现并行 二.GIL与多线程 有了GIL的存在,同一时刻同一进程中只有一个线程被执行 听到这里,有的同学立马质问:进程可以利用多核,但是开销大,而python的多线程开销

python之进程池与线程池

一.进程池与线程池介绍池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务 当并发的任务数远远超过了计算机的承受能力时,即无法一次性开启过多的进程数或线程数时就应该用池的概念将开启的进程数或线程数 池子内什么时候装进程:并发的任务属于计算密集型池子内什么时候装线程:并发的任务属于IO密集型 不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不

python并发编程之进程池,线程池concurrent.futures

进程池与线程池 在刚开始学多进程或多线程时,我们迫不及待地基于多进程或多线程实现并发的套接字通信,然而这种实现方式的致命缺陷是:服务的开启的进程数或线程数都会随着并发的客户端数目地增多而增多, 这会对服务端主机带来巨大的压力,甚至于不堪重负而瘫痪,于是我们必须对服务端开启的进程数或线程数加以控制,让机器在一个自己可以承受的范围内运行,这就是进程池或线程池的用途, 例如进程池,就是用来存放进程的池子,本质还是基于多进程,只不过是对开启进程的数目加上了限制 Python--concurrent.fu

python全栈脱产第37天------进程池与线程池、协程、gevent模块、单线程下实现并发的套接字通信

一.进程池与线程池 调用concurrent.futures下的ThreadPoolExecutor,ProcessPoolExecutor来实现 提交任务有两种方式:同步调用:提交完一个任务之后,就在原地等待,等待任务完完整整地运行完毕拿到结果后,在执行下一段代码,是串行的 异步调用:提交完一个任务之后,不在原地等待,直接运行下一段代码,任务是并发的 from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutorimp

python并发编程之进程池,线程池

要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉只要你用并发,就会有锁的问题,但是你不能一直去自己加锁吧那么我们就用QUEUE,这样还解决了自动加锁的问题由Queue延伸出的一个点也非常重要的概念.以后写程序也会用到这个思想.就是生产者与消费者问题 一.Python标准模块--concurrent.futures(并发未来) concurent.future模块需要了解的1.concurent.fut

python 之 并发编程(进程池与线程池、同步异步阻塞非阻塞、线程queue)

9.11 进程池与线程池 池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务 池子内什么时候装进程:并发的任务属于计算密集型 池子内什么时候装线程:并发的任务属于IO密集型 进程池: from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor import time,os,random ? def task(x): print('%s 接客' %os.getpid()) time.

Python 37 进程池与线程池 、 协程

一:进程池与线程池 提交任务的两种方式: 1.同步调用:提交完一个任务之后,就在原地等待,等任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行 2.异步调用:提交完一个任务之后,不是原地等待,而是直接执行下一行代码,会导致任务是并发执行的,结果future对象会在任务运行完毕后自动传给回调函数 二:协程 基于单线程下实现并发,只有一个主线程(如下图:可利用的CPU只有一个)的情况下实现并发,并发的本质:切换+保存状态 CPU正在运行一个任务,会在两种情况下自习其他任务(切换

Python 中的进程、线程、协程、同步、异步、回调

进程和线程究竟是什么东西?传统网络服务模型是如何工作的?协程和线程的关系和区别有哪些?IO过程在什么时间发生? 在刚刚结束的 PyCon2014 上海站,来自七牛云存储的 Python 高级工程师许智翔带来了关于 Python 的分享<Python中的进程.线程.协程.同步.异步.回调>. 一.上下文切换技术 简述 在进一步之前,让我们先回顾一下各种上下文切换技术. 不过首先说明一点术语.当我们说"上下文"的时候,指的是程序在执行中的一个状态.通常我们会用调用栈来表示这个状

python中的进程、线程(threading、multiprocessing、Queue、subprocess)

Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就比别人NB. 我们先了解一下什么是进程和线程. 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. 程序是运行在系统上的具有某种功能的软件,比如说浏览器,音乐播放器等. 每次执行程序的时候,都会完成一定的功能,比如说浏览器帮我们打开网页,为了保证其独立性,就需要一个专

使用concurrent.futures模块并发,实现进程池、线程池

一.关于concurrent.futures模块 Python标准库为我们提供了threading和multiprocessing模块编写相应的异步多线程/多进程代码.从Python3.2开始,标准库为我们提供了concurrent.futures模块,它提供了ThreadPoolExecutor和ProcessPoolExecutor两个类ThreadPoolExecutor和ProcessPoolExecutor继承了Executor,分别被用来创建线程池和进程池的代码.实现了对thread