You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python多进程程序仅2个子进程占用CPU的问题排查求助

问题分析与解决方案

看起来你遇到的核心问题是进程池里的大部分任务根本没被提交,导致98个进程全程闲置。让我拆解一下代码里的问题,再给你修正后的版本:

为什么大部分进程资源占用为0?

你的代码有三个关键问题:

  1. 任务拆分逻辑完全失效
    你写的for i in range(0, 1)只循环一次,加上input_files.append(os.listdir(file_path))让input_files变成了一个包含单个文件列表的二维数组。最终targetLists里只会有一个元素——也就是所有文件的完整列表。进程池只收到了这一个任务,自然只有一个子进程在干活,剩下99个进程全程闲置,资源占用当然是0。

  2. 参数传递的隐形错误
    在pool.apply_async(start_scan, args=(x))里,args需要是一个元组,但你写的(x)只是把x本身传进去,不是元组。如果x是列表,Python会把列表的每个元素当作单独参数传给start_scan,但你的start_scan只接受一个files参数,这会触发TypeError——可能你没注意到这个错误,或者被异常捕获吞掉了。

  3. 单任务内部串行处理
    就算任务拆分正确,start_scan里是逐个循环处理文件,每个scan调用都是串行执行的,根本没利用进程池的并行能力。

修正后的代码示例

我重新整理了代码,简化了逻辑,让进程池真正并行起来:

import multiprocessing as mp
import os
import time
import traceback
import logging

# 假设你的logger已经初始化完成
logger = logging.getLogger(__name__)

def scan(file_path):
    # 这里保留你原有的scan实现
    pass

def process_single_file(filedata):
    """单个文件的独立处理逻辑,交给进程池并行执行"""
    try:
        start = time.time()
        full_path = os.path.join('/home/something/test/', filedata)
        scan_result = scan(full_path)
        
        # 写入结果,建议用with保证文件正确关闭
        with open('result_clean.csv', 'a') as f:
            f.write(f"Result {scan_result} for file {filedata}\n")
        
        end = time.time()
        logger.info(f'File {filedata} processed in {end - start:.2f}s')
        return scan_result
    except Exception as e:
        logger.error(f'Failed to process {filedata}: {str(e)}')
        return None

def clean_(self, worker=100):
    # 创建进程池,worker数量建议不超过CPU核心数的2倍,避免上下文切换开销
    pool = mp.Pool(processes=worker)
    start_total = time.time()
    
    file_path = self.folder_clean_scan
    all_files = os.listdir(file_path)  # 直接获取文件列表,不是二维数组
    
    # 用pool.map自动分配任务到进程池,每个文件对应一个任务
    try:
        all_results = pool.map(process_single_file, all_files)
        print(f"Processing complete. Results: {all_results}")
    except Exception as e:
        traceback.print_exc()
    finally:
        # 必须关闭进程池并等待所有进程完成
        pool.close()
        pool.join()
    
    end_total = time.time()
    print(f"Total processing time: {end_total - start_total:.2f}s")

关键改进点

  • 真正的并行处理:用pool.map把每个文件的处理任务分发到进程池,每个进程会处理一个或多个文件,充分利用所有进程资源。
  • 简化任务拆分:不需要手动拆分文件列表,pool.map会自动完成任务分配,避免了原代码中复杂且错误的拆分逻辑。
  • 修正参数传递:map会自动把all_files的每个元素作为参数传给process_single_file,避免了元组传递的错误。
  • 资源安全:添加pool.close()和pool.join(),确保所有进程完成后再结束主进程,避免资源泄漏。

这样修改后,你的进程池里的进程都会被利用起来(实际并行数受限于CPU核心数,但不会出现98个进程完全闲置的情况),CPU和内存占用会更符合你的预期。

内容的提问来源于stack exchange,提问作者SaiKiran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:24:50