Python文件删除-";当前正在被另一个进程使用”;

Python文件删除-";当前正在被另一个进程使用”;,python,image,file-handling,Python,Image,File Handling,要求 我必须尝试创建一个程序,删除所有损坏的图像(以及小于400x400的图像),并将其余图像过滤成10000组 问题 当前,当我尝试删除任何“损坏”的图像时,会显示该文件当前正由另一个进程使用,每个错误如下: 进程无法访问该文件,因为其他进程正在使用该文件 采取的步骤 我尝试了多种方法来释放文件,包括使用“后退”策略,应用程序将移动到下一个图像,然后后退尝试删除该图像,但它仍然保持打开状态。 如果我尝试在Python打开时手动删除图像,它会顺利通过 请参见下面的代码: def confirm

要求

我必须尝试创建一个程序,删除所有损坏的图像(以及小于400x400的图像),并将其余图像过滤成10000组

问题

当前,当我尝试删除任何“损坏”的图像时,会显示该文件当前正由另一个进程使用,每个错误如下:

进程无法访问该文件,因为其他进程正在使用该文件

采取的步骤

我尝试了多种方法来释放文件,包括使用“后退”策略,应用程序将移动到下一个图像,然后后退尝试删除该图像,但它仍然保持打开状态。 如果我尝试在Python打开时手动删除图像,它会顺利通过

请参见下面的代码:


def confirmIt():
#======确认选择并将文件移动到新的子目录:
如果不是folderPath.get()=“”:##请确保不为空
source=folderPath.get()##设置源路径
大小=0
坏的=假的
对于os.listdir(源)中的fname:
如果fname.lower().endswith(扩展名):
imageName=source+“\\”+fname\35;设置图像的源位置
尝试:
img=Image.open(imageName)
宽度,高度=img.size##获取尺寸
尺寸=宽度*高度/1000
坏的=假的
img.close()
除IOError外,e:
断章取义
img.close()
如果(断开==真):
def handleRemoveReadonly(函数、路径、exc):
excvalue=exc[1]
如果func in(os.rmdir,os.remove)和excvalue.errno==errno.EACCES:
os.chmod(路径,stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
func(路径)
其他:
提升
尝试:

os.remove(imageName)##删除所有与预设要求不匹配的剩余图像(经过多次反复之后,此代码应该执行您想要的操作,除非出现任何错误:)。对任何其他人;可能会有更多的变化来消除任何扭结

from __future__ import print_function

import errno
import os

try:
    from itertools import zip_longest  # Python 3
except ImportError:  # Python 2
    from itertools import izip_longest as zip_longest  # Python 2

from PIL import Image

DEFAULT_IMAGE_EXTS = ('.jpg',)


# From the recipes section of the itertools documentation:
# https://docs.python.org/3/library/itertools.html#itertools-recipes
def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return zip_longest(*args, fillvalue=fillvalue)


def makedirs(d):
    try:
        os.makedirs(d)
    except OSError as e:
        # If the file already exists, and is a directory
        if e.errno == errno.EEXIST and os.path.isdir(d):
            created = False
        # It's some other error, or the existing file is not a directory
        else:
            raise
    else:
        created = True

    return created


def get_valid_filenames(directory, extensions):
    for filename in os.listdir(directory):
        if filename.lower().endswith(extensions):
            yield filename


def get_corrupt_image_filenames(directory, extensions=DEFAULT_IMAGE_EXTS):
    for filename in get_valid_filenames(directory, extensions):
        image_path = os.path.join(directory, filename)
        try:
            with open(image_path, 'rb') as filehandle:
                Image.open(filehandle)
                # img = Image.open(filehandle)
                # img.load()  # I don't think this is needed, unless
                #               the corruption is not in the header.
        except IOError:
            yield filename


def confirm_it(directory, extensions, images_per_dir=5000):
    # Confirm selection and move files to new sub-directory
    if directory:
        for corrupt_file_name in get_corrupt_image_filenames(directory):
            os.remove(os.path.join(directory, corrupt_file_name))

        valid_images = get_valid_filenames(directory, extensions)
        grouped_image_file_names = grouper(valid_images, images_per_dir)
        for subdir, image_filenames in enumerate(grouped_image_file_names):
            for filename in image_filenames:
                from_path = os.path.join(directory, filename)
                to_dir = os.path.join(directory, str(subdir))
                to_path = os.path.join(to_dir, filename)

                makedirs(to_dir)

                os.rename(from_path, to_path)


def confirm_it_wrapper():
    confirm_it(directory=folderPath.get(), extensions=extensions)

使用
confirm\u it\u wrapper
代替
confirm\u it
作为tkinter
按钮的回调。

您的问题是您正在修改底层文件系统(通过删除图像),然后在(旧)文件列表上循环

这就是为什么循环尝试打开不再存在的图像

解决方案是先存储文件列表,然后循环文件列表;而不是
os.listdir()
(将被缓存)的输出

您还应该考虑代码中的一些组件。请尝试以下版本:

from itertools import izip_longest

# https://docs.python.org/2/library/itertools.html
def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

def get_valid_images(image_path):
    extensions = ['*.jpg']
    return [f for f in os.listdir(image_path)
            if f.lower().endswith(extensions)]

def is_valid_image(image_path):
    try:
        img = Image.open(image_path)
        img.load()
        width, height = img.size
        img.close()
        return True
     except IOError as e:
        print(e)
        img.close()
        return None
     finally:
        img.close()
    return None

def confirmIt():
    # Confirm selection and move files to new sub-directory
    source = folderPath.get()  # set source path
    if not source:
        return False # If there is no source no point going
                     # head
    file_list = get_valid_images(source)
    valid_images = []
    for fname in file_list:
        image_dim = is_valid_image(os.path.join(source, fname))
        if image_dim:
            valid_images.append(source)

    # Now, group the resulting list in bunches for your move
    for dir_num, filenames in enumerate(grouper(valid_images, 5)):
        dest = os.path.join(source, str(dir_num))
        if not os.path.exists(dest):
            try:
                os.makedirs(dest)
            except OSError, e:
                print(e)
                continue # Skip this set, as we cannot make the dir
        for fname in filenames:
            shutil.move(fname, dest)
            print('Moving {}'.format(fname))

您确定其他进程没有保持文件打开状态吗?另外,当您甚至不使用if块时,为什么要在if块中定义
handleRemoveReadonly()
?错误消息来自哪个语句,
open
rmdir
remove
?请注意,即使另一个进程正在使用该文件,删除也应该在POSIX下工作。也许你应该考虑用你正在使用的任何OS来标记它(我想Windows)。看来你在微软下工作(我建议你使用<代码> OS.PATH。加入< /代码>而不是<代码>源+“\\”+fNeN/COD>),我不知道解锁文件的方法(可能使用<代码> cType < /Cys>用正确的SysCures)但是你可以看看是什么进程锁定了它们并试图解决这个问题。CFNZ_Technie和@Cyphase,我已经回滚了询问图像上传大小限制的编辑。这是一个单独的问题,应该作为一个单独的问题来问。嗨,布翰。。。谢谢,我没有考虑os.listdir以缓存模式存储这些内容。我将拭目以待,看看Cyphase会想出什么,因为我们已经得出了最终的工作情况,如果您有任何意见可以添加到他的中,那将非常好。@CFNZ_Techie,损坏的文件应该已经被删除,除非您删除该代码。我将很快创建一个新的问题,并给出您的答案。谢谢
from itertools import izip_longest

# https://docs.python.org/2/library/itertools.html
def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

def get_valid_images(image_path):
    extensions = ['*.jpg']
    return [f for f in os.listdir(image_path)
            if f.lower().endswith(extensions)]

def is_valid_image(image_path):
    try:
        img = Image.open(image_path)
        img.load()
        width, height = img.size
        img.close()
        return True
     except IOError as e:
        print(e)
        img.close()
        return None
     finally:
        img.close()
    return None

def confirmIt():
    # Confirm selection and move files to new sub-directory
    source = folderPath.get()  # set source path
    if not source:
        return False # If there is no source no point going
                     # head
    file_list = get_valid_images(source)
    valid_images = []
    for fname in file_list:
        image_dim = is_valid_image(os.path.join(source, fname))
        if image_dim:
            valid_images.append(source)

    # Now, group the resulting list in bunches for your move
    for dir_num, filenames in enumerate(grouper(valid_images, 5)):
        dest = os.path.join(source, str(dir_num))
        if not os.path.exists(dest):
            try:
                os.makedirs(dest)
            except OSError, e:
                print(e)
                continue # Skip this set, as we cannot make the dir
        for fname in filenames:
            shutil.move(fname, dest)
            print('Moving {}'.format(fname))