吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 737|回复: 10
收起左侧

[讨论] 关于python多进程计算MD5问题。

[复制链接]
回帖奖励 10 CB吾爱币 回复本帖可获得 1 CB吾爱币奖励! 每人限 1 次
salge 发表于 2024-1-19 13:21
脚本运行后,OS总是在一个进程里。别的进程一直不动。麻烦大家帮忙找找原因。
QQ截图20240119132000.jpg
[Python] 纯文本查看 复制代码
import os
import hashlib
import asyncio
import concurrent.futures
import multiprocessing

def calc_md5(file_path):
    # 计算文件的MD5值
    md5 = hashlib.md5()
    with open(file_path, "rb") as f:
        while True:
            data = f.read(1024000)
            if not data:
                break
            md5.update(data)
    return md5.hexdigest()

async def calc_md5_async(file_path, executor):
    # 异步地调用calc_md5函数
    loop = asyncio.get_event_loop()
    md5 = await loop.run_in_executor(executor, calc_md5, file_path)
    return md5

async def main(file_paths, executor):
    # 主函数
    tasks = [calc_md5_async(file_path, executor) for file_path in file_paths] # 任务列表
    results = await asyncio.gather(*tasks) # 等待所有任务完成
    for file_path, md5 in zip(file_paths, results):
        print(f"{file_path}: {md5}") # 打印结果

def process_start(file_paths):
    # 进程启动函数
    executor = concurrent.futures.ThreadPoolExecutor(max_workers=4) # 线程池
    asyncio.run(main(file_paths, executor)) # 运行主函数

def task_start(dir_path, flag=10000):
    # 任务启动函数
    file_paths = [] # 文件路径列表
    for root, dirs, files in os.walk(dir_path): # 遍历目录
        for file in files:
            file_paths.append(os.path.join(root, file)) # 添加文件路径
    pool = multiprocessing.Pool(processes=4) # 进程池
    for i in range(0, len(file_paths), flag): # 每flag个文件启动一个进程
        pool.apply_async(process_start, (file_paths[i:i+flag],)) # 异步地执行进程
    pool.close() # 关闭进程池
    pool.join() # 等待所有进程结束

if __name__ == "__main__":
    task_start("D:\\sd-webui-aki-v4.1\\models\\Stable-diffusion") # 读取指定目录


发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Zupup 发表于 2024-1-19 14:12

回帖奖励 +1 CB吾爱币

学到了。。。
zxtzly 发表于 2024-1-19 14:18

回帖奖励 +1 CB吾爱币

你最后给的文件夹里面有多少个文件?会不会你的flag给的太多了,总共也没那么多文件

免费评分

参与人数 1吾爱币 +2 热心值 +1 收起 理由
salge + 2 + 1 把flag改小就可以了。我改成1,cpu吃满,爽。

查看全部评分

文西思密达 发表于 2024-1-19 14:24

回帖奖励 +1 CB吾爱币

您的代码是用于计算指定目录下所有文件的MD5哈希值的。它首先使用多进程来分割文件,然后使用线程池来异步地计算每个文件的MD5值。从您提供的代码中,我发现了以下几个问题:
  • 线程与进程的混合使用:您同时使用了concurrent.futures.ThreadPoolExecutor和multiprocessing.Pool。这可能导致不必要的复杂性,因为每个子进程都会有一个自己的线程池。通常,选择进程池或线程池应该基于您的具体需求。如果您希望并行处理文件I/O操作(如读取文件),则线程可能是一个好选择。但是,如果您希望并行处理CPU密集型任务,则应该使用进程。
  • 资源管理:当使用multiprocessing.Pool时,确保在不再需要它时调用close()和join()。但在这里,由于您是在外部调用task_start函数,所以这一部分是正确的。
  • 代码可读性:虽然代码功能是明确的,但添加一些注释和文档字符串可能会使其他开发人员更容易理解您的代码。
  • 返回值:您可能想从calc_md5_async函数返回计算出的MD5值,以便在主函数中进一步处理或打印。
  • 错误处理:考虑添加异常处理来捕获潜在的错误,例如文件读取错误或计算MD5时的错误。
  • 硬编码的数字:如max_workers=4和flag=10000,考虑将这些常数定义为变量或常量,以便于管理和修改。
  • 文件路径硬编码:您在if __name__ == "__main__"中硬编码了文件路径。考虑将其作为参数传递或从配置文件中读取。
  • 关闭文件:在calc_md5函数中,您打开了一个文件但没有关闭它。虽然Python会在结束时关闭文件,但最佳实践是明确地关闭文件。
考虑到上述问题,以下是修复后的代码:
[Python] 纯文本查看 复制代码
import os  
import hashlib  
import asyncio  
import concurrent.futures  
import multiprocessing  
  
def calc_md5(file_path):  
    """计算文件的MD5值"""  
    md5 = hashlib.md5()  
    try:  
        with open(file_path, "rb") as f:  
            while True:  
                data = f.read(1024000)  
                if not data:  
                    break  
                md5.update(data)  
        return md5.hexdigest()  
    except Exception as e:  
        print(f"Error calculating MD5 for {file_path}: {e}")  
        return None  
  
async def calc_md5_async(file_path, executor):  
    """异步地调用calc_md5函数"""  
    try:  
        return await asyncio.run_in_executor(executor, calc_md5, file_path)  
    except Exception as e:  
        print(f"Error calculating MD5 for {file_path}: {e}")  
        return None  
  
async def main(file_paths, executor):  
    """主函数"""  
    tasks = [calc_md5_async(file_path, executor) for file_path in file_paths]  # 任务列表  
    results = await asyncio.gather(*tasks)  # 等待所有任务完成  
    for file_path, md5 in zip(file_paths, results):  
        print(f"{file_path}: {md5}")  # 打印结果  
  
def process_start(file_paths):  
    """进程启动函数"""  
    executor = concurrent.futures.ThreadPoolExecutor(max_workers=4)  # 线程池  
    asyncio.run(main(file_paths, executor))  # 运行主函数  
  
def task_start(dir_path, flag=10000):  
    """任务启动函数"""  
    file_paths = []  # 文件路径列表  
    for root, dirs, files in os.walk(dir_path):  # 遍历目录  
        for file in files:  
            file_paths.append(os.path.join(root, file))  # 添加文件路径  
    with multiprocessing.Pool(processes=4) as pool:  # 使用上下文管理器管理进程池  
        for i in range(0, len(file_paths), flag):  # 每flag个文件启动一个进程(尽管实际上这里只会有4个进程)  
            pool
小刘小刘 发表于 2024-1-19 15:17

回帖奖励 +1 CB吾爱币

学习一下
hjboy11 发表于 2024-1-19 15:27

回帖奖励 +1 CB吾爱币

多进程思路学习一下,不知道楼主实际测试后比单进程真的快吗?
sai609 发表于 2024-1-19 15:45

回帖奖励 +1 CB吾爱币

代码增加,进度条显示,
FlyingDragon 发表于 2024-1-19 19:29

回帖奖励 +1 CB吾爱币

需要看下目录下有多少文件,是不是都分到一个进程里了,另外,md5计算属于计算密集型,启用多线程不会加快速度,倒回拖慢速度
jueyu 发表于 2024-1-19 20:14

回帖奖励 +1 CB吾爱币

使用一下
baliao 发表于 2024-1-20 08:47

回帖奖励 +1 CB吾爱币

文西思密达 发表于 2024-1-19 14:24
您的代码是用于计算指定目录下所有文件的MD5哈希值的。它首先使用多进程来分割文件,然后使用线程池来异步 ...

请问这是AI 回答的还是人工?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 16:49

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表