文件在os.listdir中存在但因仍在复制而无法访问

2 投票
3 回答
1225 浏览
提问于 2025-04-18 09:15

我有一个Python脚本,它里面有一个while(1)的循环,这个循环会在一个特定的文件夹里查找图片文件,使用的是os.listdir这个方法。如果发现了支持的格式,它就会用PIL库把这些文件转换成PNG格式。

有时候,其他应用程序会往这个文件夹里复制一些文件(大约5MB),这个过程需要一些时间。问题是,os.listdir在复制过程开始时就能检测到每个文件的存在,但不幸的是,这些文件在复制完成之前是无法使用的。

在复制完成之前,打开文件不会抛出任何异常,使用os.access(path, os.R_OK)检查文件的访问权限也没有问题。

你有没有什么办法可以确保os.listdir报告的所有文件都是可以用的,也就是说,确保它们已经完全复制好了?

import time
import os
import shutil
import Image

#list of image formats supported for conversion
supported_formats = ['bmp', 'tga']
output_format = 'png'
output_prefix = 'prefix_'


def find_and_convert_images(search_path, destination_path, output_img_prefix, new_img_format):
    for img_file in os.listdir(search_path):
        if img_file[-3:] in supported_formats:
            print("Converting image: " + str(img_file))
            convert_image(os.path.join(search_path, img_file), new_img_format)
            converted_img_name = img_file[:-3] + new_img_format
            new_img_name = output_img_prefix + img_file[:-3] + new_img_format
            if not os.path.isdir(destination_path):
                os.makedirs(destination_path)
            try:
                shutil.move(os.path.join(search_path, converted_img_name), os.path.join(destination_path, new_img_name))
            except Exception, error:
                print("Failed to move image: " + converted_img_name + " with error: " + str(error))


def convert_image(img_file, new_img_format):
    try:
        img = Image.open(img_file)
        img.save(img_file[:-3] + new_img_format)
        del img
    except Exception, error:
        print("Failed convert image: " + img_file + " with error: " + str(error))
    try:
        os.remove(img_file)
    except Exception, error:
        print("Failed to remove image: " + img_file + " with error: " + str(error))


def main():
    images_directory = os.path.join(os.getcwd(), 'TGA')
    converted_directory = os.path.join(images_directory, 'output')
    while 1:
        find_and_convert_images(images_directory, converted_directory, output_prefix, output_format)

输出结果如下:

正在转换图片:image1.tga

转换图片失败:/TEST/TGA/image1.tga,错误信息:无法识别的图片文件

移动图片失败:image1.png,错误信息:[Errno 2] 没有这样的文件或目录:'/TEST/TGA/image1.png'

如果在运行Python脚本之前,我已经把tga文件复制到TGA文件夹里,那么一切都正常,图片会被成功转换并移动到其他目录,没有任何错误。

3 个回答

0

在我看来,文件的完整性这个概念并不存在。

你可以写一个简单的循环,让它运行1秒钟,然后检查一下文件的大小有没有变化。如果文件大小有变化,那就可以跳过这个文件。

你可以用下面的代码来获取文件的大小:

import os
file_size = os.path.getsize("/path_to_file/my_file.jpg")
0

你无法检测到“未完成”的文件;对于某些文件类型,即使数据不完整,转换也可能成功。

让负责复制文件的过程,直接把文件移动到目标位置。因为在同一个文件系统中,移动文件是一个原子操作;也就是说,完整的数据会被移动到新的位置。这其实就是一个重命名的操作。

你甚至可以在同一个文件夹内进行移动;使用一些你的脚本会忽略的文件名,然后把完成的副本移动(重命名)到目标位置。

1

你可能需要记录那些测试失败的文件,然后过一段时间再检查它们。如果它们再次失败(或者失败到一定次数),你可以标记它们为总是失败,这样下次就可以忽略它们了。

撰写回答