只需几行代码,即可实现多线程和多进程操作

Python多进程与多线程并发执行多个.py文件实战指南 在数据处理、自动化测试和后端服务开发中,提升任务执行效率是核心需求。并发编程通过允许多个任务同时执行,能够显著提高系统吞吐量和资源利用率。其核心原理在于利用计算机的多核处理器或通过时间片轮转实现任务切换。Python中实现并发主要有两大技术路径:多进程和多线程。多进程利用多个CPU核心实现真正的并行计算,尤其适合CPU密集型任务;而多线程则通过共享内存实现快速切换,更适合I/O密集型操作。理解GIL(全局解释器锁)对线程的限制是选择方案的关键。在实际工程中,使用进程池(如multiprocessing.Po 阅读详情

640?wx_fmt=jpeg

图片来源:Unsplash,作者:Karl Saare

原题 | PYTHON: A QUICK INTRODUCTION TO THE CONCURRENT.FUTURES MODULE

作者 | MASNUN

原文 | http://masnun.com/2016/03/29/python-a-quick-introduction-to-the-concurrent-futures-module.html

译者 | kbsc13("算法猿的成长"公众号作者)

声明 | 翻译是出于交流学习的目的,欢迎转载,但请保留本文出于,请勿用作商业或者非法用途

concurrent.futures 是标准库里的一个模块,它提供了一个实现异步任务的高级 API 接口。本文将通过一些代码例子来介绍这个模块常见的用法。

Executors

Executor 是一个抽象类,它有两个非常有用的子类--ThreadPoolExecutor 和 ProcessPoolExecutor 。从命名就可以知道,前者采用的是多线程,而后者使用多进程。下面将分别介绍这两个子类,在给出的例子中,我们都会创建一个线程池或者进程池,然后将任务提交到这个池子,这个池子将会分配可用的资源(线程或者进程)来执行给定的任务。

ThreadPoolExecutor

首先,先看看代码:

from concurrent.futures import ThreadPoolExecutor
from time import sleep
# 定义需要执行的任务--休眠5秒后返回传入的信息
def return_after_5_secs(message):
    sleep(5)
    return message
# 建立一个线程池,大小为 3
pool = ThreadPoolExecutor(3)

future = pool.submit(return_after_5_secs, ("hello"))
print(future.done())
sleep(5)
print(future.done())
print(future.result())

输出结果:

False
False
hello

这个代码中首先创建了一个 ThreadPoolExecutor 对象--pool ,通常这里默认线程数量是 5,但我们指定线程池的线程数量是 3。接着就是调用 submit() 方法来把需要执行的任务,也就是函数,以及需要传给这个函数的参数,然后会得到 Future 对象,这里调用其方法 done() 用于告诉我们是否执行完任务,是,就返回 true ,没有就返回 false 。

在上述例子中,第一次调用 done() 时候,并没有经过 5 秒,所以会得到 false;之后进行休眠 5 秒后,任务就会完成,再次调用 done() 就会得到 true 的结果。如果是希望得到任务的结果,可以调用 future 的result 方法。

对 Future 对象的理解有助于理解和实现异步编程,因此非常建议好好看看官方文档的介绍:

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

ProcessPoolExecutor

ProcessPoolExecutor 也是有相似的接口,使用方法也是类似的,代码例子如下所示:

from concurrent.futures import ProcessPoolExecutor
from time import sleep

def return_after_5_secs(message):
    sleep(5)
    return message

pool = ProcessPoolExecutor(3)

future = pool.submit(return_after_5_secs, ("hello"))
print(future.done())
sleep(5)
print(future.done())
print("Result: " + future.result())

输出结果:

False
False
Result: hello

通常,我们会用多进程 ProcessPoolExecutor 来处理 CPU 密集型任务,多线程 ThreadPoolExecutor 则更适合处理网络密集型 或者 I/O 任务。

尽管这两个模块的接口相似,但 ProcessPoolExecutor 采用的是 multiprocessing 模块,并且不会被 GIL( Global Interpreter Lock) 所影响。不过对于这个模块,我们需要注意不能采用任何不能序列化的对象。

Executor.map()

上述两个模块都有一个共同的方法--map()。跟 Python 内建的 map 函数类似,该方法可以实现对提供的一个函数进行多次调用,并且通过给定一个可迭代的对象来将每个参数都逐一传给这个函数。另外,采用 map() 方法,提供的函数将是并发调用。

对于多进程,传入的可迭代对象将分成多块的数据,每块数据分配给每个进程。分块的数量可以通过调整参数 chunk_size ,默认是 1.

下面是官方文档给出的 ThreadPoolExecutor 的例子:

import concurrent.futures
import urllib.request

URLS = ['http://www.baidu.com/',
        'http://www.163.com/',
        'http://www.126.com/',
        'http://www.jianshu.com/',
        'http://news.sohu.com/']

# Retrieve a single page and report the url and contents
def load_url(url, timeout):
    with urllib.request.urlopen(url, timeout=timeout) as conn:
        return conn.read()

# We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    # Start the load operations and mark each future with its URL
    future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
    for future in concurrent.futures.as_completed(future_to_url):
        url = future_to_url[future]
        try:
            data = future.result()
        except Exception as exc:
            print('%r generated an exception: %s' % (url, exc))
        else:
            print('%r page is %d bytes' % (url, len(data)))

输出结果:

'http://www.baidu.com/' page is 153759 bytes
'http://www.163.com/' page is 693614 bytes
'http://news.sohu.com/' page is 175707 bytes
'http://www.126.com/' page is 10521 bytes
'http://www.jianshu.com/' generated an exception: HTTP Error 403: Forbidden

而对于 ProcessPoolExecutor ,代码如下所示:

import concurrent.futures
import math

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 concurrent.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__':
    main()

输出结果:

112272535095293 is prime: True
112582705942171 is prime: True
112272535095293 is prime: True
115280095190773 is prime: True
115797848077099 is prime: True
1099726899285419 is prime: False
as_completed() & wait()

concurrent.futures 模块中有两个函数用于处理进过 executors 返回的 futures,分别是 as_completed() 和 wait()。

as_completed() 函数会获取 Future 对象,并且随着任务开始处理而返回任务的结果,也就是需要执行的函数的返回结果。它和上述介绍的 map() 的主要区别是 map() 方法返回的结果是按照我们传入的可迭代对象中的顺序返回的。而 as_completed() 返回的结果顺序则是按照任务完成的顺序,哪个任务先完成,先返回结果。

下面给出一个例子:

from concurrent.futures import ThreadPoolExecutor, wait, as_completed
from time import sleep
from random import randint

def return_after_5_secs(num):
    sleep(randint(1, 5))
    return "Return of {}".format(num)

pool = ThreadPoolExecutor(5)
futures = []
for x in range(5):
    futures.append(pool.submit(return_after_5_secs, x))

for x in as_completed(futures):
    print(x.result())

输出结果

Return of 3
Return of 4
Return of 0
Return of 2
Return of 1

wait() 函数返回一个包含两个集合的带有名字的 tuple,一个集合包含已经完成任务的结果(任务结果或者异常),另一个包含的就是还未执行完毕的任务。

同样,下面是一个例子:

from concurrent.futures import ThreadPoolExecutor, wait, as_completed
from time import sleep
from random import randint

def return_after_5_secs(num):
    sleep(randint(1, 5))
    return "Return of {}".format(num)

pool = ThreadPoolExecutor(5)
futures = []
for x in range(5):
    futures.append(pool.submit(return_after_5_secs, x))

print(wait(futures))

输出结果:

DoneAndNotDoneFutures(done={<Future at 0x2474aa4fba8 state=finished returned str>, <Future at 0x2474a903048 state=finished returned str>, <Future at 0x2474aa4fa58 state=finished returned str>, <Future at 0x2474aa4fcf8 state=finished returned str>, <Future at 0x2474a8beda0 state=finished returned str>}, not_done=set())

我们可以通过指定参数来控制 wait() 函数返回结果的时间,这个参数是 return_when,可选数值有:FIRST_COMPLETED, FIRST_EXCEPTION 和 ALL_COMPLETED。默认结果是 ALL_COMPLETED ,也就是它会等待所有任务都执行完成才返回结果。


以上就是本次教程的所有内容,代码已经上传到:

https://github.com/ccc013/Python_Notes/blob/master/Tutorials/concurrent_futures_tutorial.py

linux上实现多进程和多线程实现同步互斥(源代码) 在linux上分别用多进程和多线程实现的同步互斥操作(源代码) 立即下载

相关推荐

事件相机数据处理实战:从原始事件流到视觉表征的三种核心方法

本文深入探讨了事件相机数据处理的核心环节,即如何将异步、稀疏的原始事件流转换为深度学习模型可处理的视觉表征。文章重点解析了三种核心方法:逐通道累积、体素网格双线性插值和对称累积事件表示,详细阐述了其原理、代码实现、可视化效果及各自的适用场景,为事件相机在目标识别、光流估计等视觉任务中的高效应用提供了实战指南。

read5的博客 438

爬虫(七)--程序,多进程,多线程

爬取网站的流程: 确定网站哪个url是数据的来源 简要分析网站结构,查看数据在哪里 查看是否有分页,解决分页问题 发送请求,查看response.text里面是否有我们想要的数据 如果有数据,提取,保存 如果没有,我们就可以通过以下两种方式来实现爬取 分析数据来源,查看是否可以通过一些接口获取数据(首推) 应该首先想到,数据可能是从ajax接口中获取的。 分析接口的步骤...

一个非常正经的人的博客 573

谷歌账号国家或地区设置修改全攻略:条件、流程与避坑指南

谷歌账号的国家或地区设置与付款资料、账号历史行为及登录环境强绑定,修改时需满足特定条件。其原理在于地区作为索引键,关联内容库、货币结算和风控策略。正确切换可解决内容推荐错乱、付款失败等问题,适用于搬家、订阅区域限定服务等场景。操作前需在目标地区创建付款资料、清空余额并取消订阅,且一年仅能修改一次。本文详解从准备到验证的完整流程,并揭示官方文档未提及的实操陷阱,助你安全完成地区切换。

weixin_42521558的博客 2322

python爬虫之多线程、多进程+代码示例

python爬虫之多线程、多进程 使用多进程、多线程编写爬虫的代码能有效的提高爬虫爬取目标网站的效率。 很多人学习python,不知道从何学起。 很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。 很多已经做案例的人,却不知道如何去学习更加高深的知识。 那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码! QQ群:101677771 一、什么是进程和线程 引用廖雪峰的官方网站关于进程和线程的讲解: 进程:对于操作系统来说,一个任务就..

Python学习Q群696455390 724

保姆级教程:用GROMACS的FEP方法计算小分子结合自由能(附完整mdp配置)

本文提供了一份详细的GROMACS自由能微扰(FEP)计算教程,涵盖从系统准备、参数配置到结果分析的全流程。通过具体案例演示如何计算小分子结合自由能,包括λ窗口设计、动力学参数优化及并行化执行技巧,帮助研究者克服FEP计算中的常见问题,获得可靠的自由能数据。

weixin_30598225的博客 353

绿联NAS使用docker部署immich【pro系统】

随后去绿联你想要存放immich的地方创建一个文件夹,便于区分,如图,我创建了一个immich的文件夹。1.进入文件夹后面是有斜杠的(tips:只需要敲击前面几个字母,按tab键自动补全)cd:进入路径,1.可以是当前的下一层相对路径 2.也可以是完整的全路径。前言:好像没有绿联的教程,刚好自己也有需求,就顺便记录了。如果你的挂载实战情况比较复杂,接下来是喂到胃里的知识点。】下载文件(群晖的,别慌,能用),两份,红框的就是。首先,没什么好说的,去immich官网【点击1.终端,2.新增,3.确定。

weixin_45343644的博客 1779

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

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

weixin_30342827的博客 319

利用GPAC生成MP4文件

GPAC主要针对学生和内容创作者,代表了一个跨平台的多媒体框架,开发人员可以使用它在 LGPL 许可下制作开源媒体。GPAC多媒体框架兼容范围广泛的流行文件类型,从常见格式(如 AVI、MPEG 和 MOV)到复杂格式(如 MPEG-4 系统或 VRML/X3D)和 360 电影。

深之JohnChen的专栏 1771

Ptyhon教程:只需几行代码,即可实现多线程和多进程操作

concurrent.futures是标准库里的一个模块,它提供了一个实现异步任务的高级 API 接口。本文将通过一些代码例子来介绍这个模块常见的用法。 Executors Executor 是一个抽象类,它有两个非常有用的子类–ThreadPoolExecutor和ProcessPoolExecutor。从命名就可以知道,前者采用的是多线程,而后者使用多进程。 下面将分别介绍这两个子类,在给出的例子中,我们都会创建一个线程池或者进程池,然后将任务提交到这个池子,这个池子将会分配可用的资源(线程或者进程)来

python学习者的博客 199

TCP/IP协议栈之LwIP(三)---网际寻址与路由(IPv4 + ARP + IPv6)

一、网际寻址原理 当网络设备地址总数并不是很多的情况下,有了唯一地址(比如MAC地址)就可以定位相互通信的主体。然而,当地址总数越来越多时,如何高效地从中找出通信的目标地址将成为一个重要的问题。为此人们发现地址除了具有唯一性还需要具有层次性。MAC地址虽然具有唯一性,但没有层次性,也即当网络设备增加到一定程度,需要将网络分成多个数据链路时,MAC地址无法跨链路寻址,是真正负责最终通信的地址。要实现跨局域网的网际寻址,就要靠具有层次性的网络IP地址实现了。

流云 6819

Keil中搭建自动化单元测试框架Unity

前言:   虽然一些C++的自动化单元测试框架也能用来C语言单元测试,但那样我们编写C语言程序时需要符合C++的标准,这样有一些C的特性是无法使用的,限制C的特性使用不太好,于是找了一个全部用C实现的自动化测试框架。Unity是一个简单且直接的自动化单元测试框架,它由很少的几个文件构成。 搭建环境:   1.从github上下载最新版本的Unity源码,下载链接:https://github...

程序员的自我修炼 3900

Python爬虫的多线程与多进程的使用场景,以及使用实例代码

本文主要综合三篇文章的内容,分为三个方面理解进程与线程。 前言 python可以实现多线程的方法有 thread(低版本使用的),threading Queue multiprocessing 其中threading客户以通过实例方法或者类方法来创建 多线程。 multiprocessing方法可以创建多线程池,用起来比较简洁、方便。 两者的比较 multiproces...

NeverLate_gogogo的博客 2606

万字长文解密:SAP Fiori 首屏加载缓慢背后的真相

什么是一个健康理想的 Fiori 首次加载状态?FLP 首页不臃肿,用户默认看见的内容不多但足够用缓存作业按规则运行,冷启动不至于每次都从零开始应用首屏只读必要数据,UI5 资源经过 preload,视图异步加载OData 服务字段克制、分页合理、缓存分层清楚后台 CDS 与 HANA 只为当前屏幕做最必要的工作。只要这些标准同时满足,用户第一次打开 Fiori 页面的体感通常会从明显卡顿变成可接受甚至顺滑。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 557

python爬虫用多线程还是多进程_有没有易懂的 Python 多线程爬虫代码

展开全部Python 在程序并行化2113方面多少有些声名狼藉。撇开5261技术上的问题,例如线程4102的实现和 GIL1,我觉得错误的教学指1653导才是主要问题。常见的经典 Python 多线程、多进程教程多显得偏“重”。而且往往隔靴搔痒,没有深入探讨日常工作中最有用的内容。传统的例子简单搜索下“Python 多线程教程”,不难发现几乎所有的教程都给出涉及类和队列的例子:#Example.p...

weixin_39792472的博客 113

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Python多进程、多线程、协程学习小结

| 导语最近利用Python写数据处理相关的工具,正好研究一下Python中的多进程、多线程以及协程相关基础知识,分享给有需要的同学~ 1、Python多进程 在Unix/Linux中系统内核提供了fork系统调用来创建进程,根据不同的返回值来判断当前进程是子进程还是父进程,C语言代码示例如下: #include <unistd.h> #include <stdio.h> int main (){ //pid表示fork函数返回的值 int pid;.

LingDuS的博客 309

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Redis的多线程与多进程

事实上,redis是支持多进程与多线程的(从2.x?之后),而不是网上千篇一律的redis单线程单进程。 多进程分析: int rdbSaveBackground(char *filename) { pid_t childpid; long long start; ...

chutibeng7204的博客 444

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

mysql+多进程+多线程_Redis的多线程与多进程

事实上,redis是支持多进程与多线程的(从2.x?之后),而不是网上千篇一律的redis单线程单进程。多进程分析:int rdbSaveBackground(char *filename) {pid_t childpid;long long start;if (server.rdb_child_pid != -1) return REDIS_ERR;server.dirty_before_bgs...

weixin_39752157的博客 242

Python爬虫——多进程multiprocessing

其实多进程相对来说不是特别适合用来做爬虫,因为多进程比较适用于计算密集型,而爬虫是IO密集型,因此多进程爬虫对速度的提升不是特别明显,但是将爬虫改为多进程比较简单,只需简单的几行代码即可搞定,所以在修改我的爬虫提升效率时,我最先实现的是多进程爬虫。(然而速度真心还是慢,我多线程+协程的程序跑的晚,却早已经结束工作了,多进程的还在苦战…) 下面我通过实例来进行介绍。 我爬取的数据是外文数...

明月清風 6732

怎样用一行 Python 代码实现并行

Python 在程序并行化方面多少有些声名狼藉。撇开技术上的问题,例如线程的实现和 GIL,我觉得错误的教学指导才是主要问题。常见的经典 Python 多线程、多进程教程多显得偏"重"。而且往往隔靴搔痒,没有深入探讨日常工作中最有用的内容。 传统的例子 简单搜索下"Python 多线程教程",不难发现几乎所有的教程都给出涉及类和队列的例子: import os import PIL from multiprocessing import Pool from PIL import Image SI

chen801090的博客 344

多线程PV操作

这是一次测验的编程题,涉及到多线程、信号量、PV操作等,刚好是自己的薄弱部分,记录一下 是一个代码补全题,并不是完全手撸,核心代码也就PV操作那几行 题目 考试系统还没开放查询,后期来补,先大致凭记忆叙述一下 有一个临界资源num=0,一个线程+1,另一个线程-1,但是要求两个线程交替执行,使最终结果是1,0,1,0,1…… 答案 这个自己写的,不是官方的答案,不严谨之处恳求大佬指点一二 #include <stdio.h> #include <stdlib.h> #include

怡宝的踩坑之路 1099

Linux C并发编程实战:生产者/消费者模型的多进程与多线程实现

并发编程是构建高性能、高响应软件系统的核心技术,其核心挑战在于管理多个执行单元对共享资源的访问,以避免竞态条件和数据不一致。其基本原理是通过同步原语协调线程或进程的执行顺序。掌握并发编程的技术价值在于能够设计出高效、稳定且可扩展的应用程序,尤其在服务器后端、实时数据处理等场景中至关重要。生产者/消费者问题作为并发编程的经典模型,完美体现了对共享缓冲区、速度匹配和正确性保证的实践需求。本文以Linux C为环境,深入探讨了分别使用多进程(涉及进程间通信IPC与命名信号量)和多线程(使用互斥锁与条件变量)两种架

weixin_32924297的博客 334

快捷:利用python多进程加速日常工作中的for循环操作

本文介绍了如何利用python多进程来加速处理for循环操作的方式,该方案可以处理多进程带有返回值的情景,并结合tqdm模块动态显示进程的处理进度。

7401

Python开发,制作高大上的进度条,几行代码就搞定了?

![????/upload-images.jianshu.io/upload_images/18829896-2291c22a8e734e04.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 对于开发或者运维来说,使用Python去完成一些跑批任务,或者做一些监控事件是非常正常的情况。那么如何有效的监控任务的进度,除了在任务中加上log外,...

Python这样学 974

一行 Python 实现并行化 -- 日常多线程操作的新思路

转自: http://www.zhangzhibo.net/2014/02/01/parallelism-in-one-line/ http://chriskiehl.com/article/parallelism-in-one-line/ Python 在程序并行化方面多少有些声名狼藉。撇开技术上的问题,例如线程的实现和 GIL1,我觉得错误的教学指导才是主要问题。常见的...

weixin_30820151的博客 80
上一篇: 他用1年时间,从负债6万到年入百万:最会赚钱的人,都在做这件事
下一篇: 【只推荐一位】技术好、三观正,坐拥20W粉丝的原创技术号
菜鸟学Python
博客等级 码龄9年 8062粉丝 571原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值