首页 > 编程问答 >为什么使用 Pool 重命名时我的文件数量会减少?

为什么使用 Pool 重命名时我的文件数量会减少?

时间:2024-07-18 17:47:40浏览次数:21  
标签:python-3.x

我想并行重命名文件,这里我选择使用 Pool 来做到这一点。

def rename_files(folder, prefix, n):
    files = os.listdir(folder)
    n = 4
    tasks = [
        (
            os.path.join(folder, file),
            os.path.join(
                folder,
                f"{prefix}{i+1:0{n}}{Path(file).suffix}",
            ),
        )
        for i, file in enumerate(files)
    ]

    with Pool(os.cpu_count() // 2) as pool:
        pool.starmap(rename_file, tasks)

当我多次执行它时,我的文件数量不知何故减少,有人可以解释一下吗?

操作系统:Linux 22.04

python:3.12.3


你的代码中存在一个潜在的竞争条件,这可能会导致文件丢失:

问题:

你正在枚举文件并同时创建重命名任务。如果在创建所有任务之前文件夹中的文件发生变化(例如,添加或删除文件),则 enumerate(files) 的结果与 pool.starmap 开始处理任务时的实际文件列表可能不同步。

示例:

  1. 假设你的文件夹中有 file1.txt file2.txt file3.txt
  2. 代码枚举文件并创建了三个重命名任务。
  3. pool.starmap 开始处理任务 之前 ,另一个进程或程序删除了 file2.txt
  4. pool.starmap 开始处理任务,并成功重命名了 file1.txt file3.txt
  5. 但是,由于 file2.txt 不再存在,因此与其对应的重命名任务将会失败。更糟糕的是,由于文件列表的偏移, file3.txt 的重命名目标会被错误地应用于原本应该用于 file2.txt 的新文件名。

结果: 你丢失了一个文件 ( file2.txt ),并且另一个文件 ( file3.txt ) 被错误地重命名。

解决方案:

为了避免此问题,你应该在创建任务 之前 收集所有文件名,并确保在处理过程中文件列表不会更改:

import os
from multiprocessing import Pool
from pathlib import Path


def rename_files(folder, prefix, n):
    # 在创建任务之前获取所有文件名
    files = os.listdir(folder)

    n = 4
    tasks = [
        (
            os.path.join(folder, file),
            os.path.join(
                folder,
                f"{prefix}{i+1:0{n}}{Path(file).suffix}",
            ),
        )
        for i, file in enumerate(files)
    ]

    with Pool(os.cpu_count() // 2) as pool:
        pool.starmap(rename_file, tasks)

其他建议:

  • 你还可以考虑使用 os.rename(src, dst) 来代替 rename_file 函数,因为它是由操作系统直接提供的原子操作,可以避免一些潜在的错误。
  • 为了更好地处理错误,你可以让 rename_file 函数返回一个布尔值或错误信息,然后在主进程中检查结果。

标签:python-3.x
From: 78763626

相关文章

  • 无法在 Rasp pi 4B 上安装 python 库
    :~$sudopipinstall序列号错误:外部管理环境×该环境是外部管理的╰─>要在系统范围内安装Python软件包,请尝试aptinstallpython3-xyz,其中xyz是您要尝试的包安装。Ifyouwishtoinstallanon-Debian-packagedPythonpackage,createavirtualenvironme......
  • python学习之---迭代器与生成器
    什么是迭代器可迭代对象:可以通过for循环来实现遍历,例如list、string、dict迭代器:不仅可以使用for循环,还可以使用next()方法、__iter__()next():获取容器中的下一个元素,当容器中没有可访问的元素后,next()方法将会抛出一个StopIteration异常终止迭代器iter():内建函数获取......
  • Python web自动化爬虫-selenium/处理验证码/Xpath
    #coding:utf-8importtimeimportrandomfromtimeimportsleepfromcsvimportwriterfromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromchaojiyingimportChaojiying_Clientfromselenium.webdriverimportActionChainsdriver......
  • 【Python】通过Cython提升性能
    一、什么是Cython,如果你了解Python,就会知道Python相比于其他语言,性能差了不是一点半点。但是Python的底层实现大量使用了C语言,可以与C语言很好的结合。并且在Python中由于GIL全局解释器锁的机制,导致python在实现CPU密集型操作时非常吃力。Cython是Python的一个扩展,用于将Python代......
  • Python学习:Python数据类型大盘点
    Python的数据类型非常丰富,它们为编程提供了强大的工具来处理各种数据。以下是对Python数据类型的详细盘点:数值类型:整型(Integers):用于表示整数,可以是正数、负数或零。在Python中,整型可以表示的数值范围是平台特定的。浮点型(FloatingPointNumbers):用于表示带有小数部分的数......
  • 【Python】通过Cython提升性能
    一、什么是Cython,如果你了解Python,就会知道Python相比于其他语言,性能差了不是一点半点。但是Python的底层实现大量使用了C语言,可以与C语言很好的结合。并且在Python中由于GIL全局解释器锁的机制,导致python在实现CPU密集型操作时非常吃力。Cython是Python的一个扩展,用于将Py......
  • 【Python】使用PySide6 + Qt Designer创建简易用户界面(含用户交互)
    【Python】使用PySide6+QtDesigner创建简易用户界面(含用户交互)文章目录【Python】使用PySide6+QtDesigner创建简易用户界面(含用户交互)相关代码运行环境操作过程1.PySide6和QtDesigner的安装2.创建外部工具PyUIC和QtDesigner3.QtDesigner的简单使用说明4.完整代......
  • 一个python代码
     一个python代码importosimportnumpyasnpimportrefrompathlibimportPathoutput_folder='./data'filename_lineEdge=r'./data/fx0022/dom1lines_Edge.txt'filename_jgw=r'./data/fx0022/test/dom1.jgw'#读取线段文件data=[]i=......
  • 基于SpringBoot的宠物领养系统-07863(免费领源码+开发文档)可做计算机毕业设计JAVA、PHP
    摘 要21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识,科学化的管理,使信息存储达到准确、快速、完善,并能提高工作管理效率,促进其发展。论文主要是对宠物领养系统......
  • ubuntu 20 pyenv安装python环境
    安装pyenvgitclonehttps://github.com/pyenv/pyenv.git~/.pyenv或者自动安装程序curlhttps://pyenv.run|bash依赖库sudoapt-getupdatesudoapt-getupgradesudoapt-getinstallgccmakezlib1g-devdist-upgradesudoapt-getinstalllibbz2-devbuild-essenti......