python:并发编程(十六)

这篇具有很好参考价值的文章主要介绍了python:并发编程(十六)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

本文将和大家一起探讨python并发编程的实际运用,会以一些我实际使用的案例,或者一些典型案例来分享。本文使用的案例是我实际使用的案例(上篇),是基于之前效率不高的代码改写成并发编程的。让我们来看看改造的过程,这样就会对并发编程的高效率有个清晰地认知,也会在改造过程中学到一些知识。

本文为python并发编程的第十六篇,上一篇文章地址如下:

python:并发编程(十五)_Lion King的博客-CSDN博客

下一篇文章地址如下:

python:并发编程(十七)_Lion King的博客-CSDN博客

一、改造对象

1、案例地址

python:根据灰度值检查成像是否存在黑图情况_python 判断图片是否有黑边_Lion King的博客-CSDN博客

import os
from PIL import Image
 
def image_gray(img):
    # 打开图片
    img = Image.open(img)
 
    # 计算平均灰度值
    gray_sum = 0
    count = 0
    for x in range(img.width):
        for y in range(img.height):
            if img.mode == "RGB":
                r, g, b = img.getpixel((x, y))
                gray_sum += (r + g + b) / 3
            elif img.mode == "L":
                gray_value = img.getpixel((x, y))
                gray_sum += gray_value
            count += 1
 
    avg_gray = gray_sum / count
    return avg_gray
 
def find_image(folder_path):
    # 定义一个列表存储图片路径
    images = []
    # 遍历文件夹下的所有文件
    for root, dirs, files in os.walk(folder_path):
        for file in files:
            file_path = os.path.join(root, file)
            # 处理每个文件,将其添加到列表中
            images.append(file_path)
    return images
 
def assert_run(folder_path):
    images=find_image(folder_path)
    for img in images:
        gray = image_gray(img)
        # 灰度值小于50,将认为是黑图
        if gray < 50:
            print(img, ":", gray)
 
if __name__ == "__main__":
    # image_gray()
    # find_image()
    folder_path = r'D:\黑图'
    assert_run(folder_path)
 

这里简单介绍一下这段代码:这段代码是一个简单的图像处理程序,用于找出指定文件夹中的黑图像。代码首先定义了一个image_gray函数,用于计算图像的平均灰度值。然后定义了一个find_image函数,用于遍历指定文件夹下的所有文件,并返回图像文件的路径列表。最后,在assert_run函数中,使用find_image函数获取指定文件夹中的图像路径列表,并对每个图像调用image_gray函数计算平均灰度值,如果平均灰度值小于50,则打印该图像的路径和灰度值。

整体流程如下:

(1)导入必要的模块:os用于操作文件和文件夹,PIL用于图像处理。

(2)定义image_gray函数:打开图像文件,计算图像的平均灰度值。

(3)定义find_image函数:遍历指定文件夹下的所有文件,返回图像文件的路径列表。

(4)定义assert_run函数:调用find_image函数获取指定文件夹中的图像路径列表,对每个图像调用image_gray函数计算平均灰度值,如果小于50则打印图像路径和灰度值。

(5)在if __name__ == "__main__":代码块中,指定一个文件夹路径作为参数,调用assert_run函数执行图像处理。

请注意,代码中使用了PIL库来处理图像,确保你已经安装了该库,可以使用pip install Pillow来安装。此外,要确保指定的文件夹中包含图像文件,并且文件的格式受PIL库支持。

2、性能问题排查

为方便排查性能问题,我们需要在上面代码的基础上加一个计算耗时的装饰器,程序如下:

def calculate_runtime(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        runtime = end_time - start_time
        print(f"程序运行时间:{runtime}秒")
        return result
    return wrapper

(1)先测算assert_run函数的时间,即整体时间。如下图,485张图片耗时约1933秒,约32分钟左右处理完这些图片。

python:并发编程(十六)

 (2)再测算image_gray函数的时间,即处理一张图的时间,大概需要4秒左右。

python:并发编程(十六)

 (3)接着测算将图片假如列表的时间,几乎可以忽略不计。

python:并发编程(十六)

 综上,处理一张图需要的时间很长,这是导致整个脚本运行时间很长的根本原因。因此,优化的点应该是使用并发编程同时处理多个图片、使用并发编程处理一个图片的灰度值、解决一个图片耗时长的问题(如用更快的模块来处理灰度值)。

二、实施方案:使用多进程同时处理多个图片

虽然直接解决一个图片的耗时,能够让这个任务时间瞬间变短很多,但是,为了方便观察耗时,我们先让处理一张图片的时间保持为4秒左右,基于这个,我们采用并发编程的方式,优化整体时间。

1、先修改代码,让其处理4张图片,方便调试

python:并发编程(十六)

2、改造 assert_run 函数为多进程并发

import os
from PIL import Image
import time
import concurrent.futures

def calculate_runtime(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        runtime = end_time - start_time
        print(f"程序运行时间:{runtime}秒")
        return result
    return wrapper

@calculate_runtime
def image_gray(img):
    # 打开图片
    img = Image.open(img)

    # 计算平均灰度值
    gray_sum = 0
    count = 0
    for x in range(img.width):
        for y in range(img.height):
            if img.mode == "RGB":
                r, g, b = img.getpixel((x, y))
                gray_sum += (r + g + b) / 3
            elif img.mode == "L":
                gray_value = img.getpixel((x, y))
                gray_sum += gray_value
            count += 1

    avg_gray = gray_sum / count
    return avg_gray

@calculate_runtime
def find_image(folder_path):
    # 定义一个列表存储图片路径
    images = []
    # 遍历文件夹下的所有文件
    for root, dirs, files in os.walk(folder_path):
        for file in files:
            file_path = os.path.join(root, file)
            # 处理每个文件,将其添加到列表中
            images.append(file_path)
    return images[0:4]

def process_image(img):
    gray = image_gray(img)
    # 灰度值小于50,将认为是黑图
    if gray < 50:
        print(img, ":", gray)

@calculate_runtime
def assert_run(folder_path):
    images = find_image(folder_path)

    with concurrent.futures.ProcessPoolExecutor(max_workers=10) as executor:
        # 提交任务并发执行
        futures = [executor.submit(process_image, img) for img in images]

        # 等待所有任务完成
        concurrent.futures.wait(futures)


if __name__ == "__main__":
    folder_path = r'C:\Users\yeqinfang\Desktop\临时文件\文件存储'
    assert_run(folder_path)





处理4张图片时,在没有采用多进程的情况下,脚本运行需要16秒,改了多进程(启用10个进程)后,运行时间为5秒左右。

python:并发编程(十六)

3、一些小实验

不同进程处理40张图片的耗时情况,如下几个图片:

1个进程时,40张图片耗时 192 秒

5个进程时,40张图片耗时 46 秒

10个进程时,40张图片耗时 38 秒

15个进程时,40张图片耗时 38 秒

20个进程时,40张图片耗时 38 秒

60个进程时,40张图片耗时 44 秒

这样的现象是不是有点意思呢?后续文章我们再对其进行分析,我们先简单了解一下咋们的系统,看一下我系统的内核数量,可执行cmd指令:

wmic cpu get NumberOfCores

显示的内核储量为6,在一个具有6个物理内核的系统上,并发执行的进程数量通常应该小于或等于物理内核的数量。这是因为每个物理内核都可以独立执行一个进程,同时超过物理内核数量的进程可能会导致竞争和性能下降。

但需要注意的是,并发执行的进程数量还受到其他因素的影响,如系统负载、资源需求等。在决定并发执行的进程数量时,需要综合考虑系统的性能和资源利用情况。可以根据实际情况进行测试和调整,观察并发执行不同数量进程时的性能表现,选择最优的进程数量。

python:并发编程(十六)

 python:并发编程(十六)

 python:并发编程(十六)

 python:并发编程(十六)

 python:并发编程(十六)

 python:并发编程(十六)

4、使用10个进程处理485张图片

在没有使用并发之前,我们处理485张图片耗时约1933秒,约32分钟左右处理完这些图片。

在使用多进程并发之后,我们处理485张图片耗时约481秒,约8分钟左右处理完这些图片。

这种情况,多进程就有话说了:普通编程编不了的程,由我多进程来编,还有,你听好,普通编程不敢编的程我编,普通编程不敢管的事我管,一句话,普通编程管得了的我要管,普通编程管不了的我更要管,这就是多进程,够不够清楚!

python:并发编程(十六)文章来源地址https://www.toymoban.com/news/detail-490050.html

到了这里,关于python:并发编程(十六)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 半路出家自学当程序员这一年的经历,大家一起共勉

    2022年3月7日,我来到了上海。那是一个寒冷的夜晚。虽然因为提前找到了工作,心里还是比较踏实的。当时是我的牛马兄弟来接的我,然后我们住在了一起。这才使得我当时月薪4,000的人能够在上海得以生存。 来到上海没多久就出现了疫情,当时真的挺惨的。基本上一直是被

    2023年04月18日
    浏览(56)
  • 如何把aac转化为mp3?大家和我一起往下学习

        如何把aac转化为mp3?aac是一种先进的音频编码格式,通过较小的文件大小提供出色的音质体验。然而,由于其相对较少的普及度,与MP3相比,兼容性稍显不足,有些播放器可能无法直接识别aac格式。在某种程度上,我们可以将aac格式称为一种小众格式。考虑到这一点,一

    2024年02月11日
    浏览(36)
  • python:并发编程(十二)

    本文将和大家一起探讨python的多协程并发编程 (下篇) ,使用内置基本库asyncio来实现并发,先通过官方来简单使用这个模块。先打好基础,能够有个基本的用法与认知,后续文章,我们再进行详细使用。 本文为python并发编程的第十二篇,上一篇文章地址如下: python:并发

    2024年02月09日
    浏览(33)
  • python并发编程

    多线程:threading,利用CPU和IO可以同时执行的原理,让CPU不会干巴巴等待IO完成; 多进程:multiprocess,利用多核CPU的能力,真正的并行执行任务; 异步IO:asyncio,当线程比较多时,切换线程也会占用CPU资源,可在单线程中利用CPU和IO同时执行的原理,实现函数异步执行; 使用

    2024年02月11日
    浏览(37)
  • python:并发编程(九)

    本文将和大家一起探讨python的多线程并发编程 (下篇) ,使用内置基本库threading来实现并发,先通过官方来简单使用这个模块。先打好基础,能够有个基本的用法与认知,后续文章,我们再进行详细使用。 本文为python并发编程的第九篇,上一篇文章地址如下: python:并发编

    2024年02月09日
    浏览(34)
  • python:并发编程(十三)

    本文将和大家一起探讨python提供高级接口(进程池、线程池)的并发编程,使用内置基本库concurrent.futures来实现并发,先通过官方来简单使用这个模块。先打好基础,能够有个基本的用法与认知,后续文章,我们再进行详细使用。为什么说是concurrent.futures,而不是concurrent呢?

    2024年02月09日
    浏览(35)
  • python:并发编程(十五)

    本文将和大家一起探讨python并发编程的第三方模块,他们都是一些高度集成的模块,可运用于特定的场景。也就是,如果期望在特定领域实现并发编程,可以不需要只依赖python的内置并发编程模块,可更加高效地实现并发编程。 本文为python并发编程的第十五篇,上一篇文章地

    2024年02月09日
    浏览(40)
  • python:并发编程(一)

    本文将和大家一起探讨并发编程,而不限于python语言。后续文章,我们将一起学习并发编程的相关模块。为什么专门写并发编程的文章呢?一个重要原因是有趣,而且实用。写一些简单的脚本可能很少用到并发编程,但是要提高这些脚本的工作效率,并发编程是个不错的选择

    2024年02月09日
    浏览(37)
  • python:并发编程(二十三)

    本文将和大家一起探讨python并发编程的实际项目:win图形界面应用 (篇五,共八篇) ,系列文章将会从零开始构建项目,并逐渐完善项目,最终将项目打造成适用于高并发场景的应用。 本文为python并发编程的第二十三篇,上一篇文章地址如下: python:并发编程(二十二)

    2024年02月11日
    浏览(41)
  • python:并发编程(二十四)

    本文将和大家一起探讨python并发编程的实际项目:win图形界面应用 (篇六,共八篇) ,系列文章将会从零开始构建项目,并逐渐完善项目,最终将项目打造成适用于高并发场景的应用。 本文为python并发编程的第二十四篇,上一篇文章地址如下: python:并发编程(二十三)

    2024年02月11日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包