【问题标题】:Wait for Windows file I/O to complete in Python在 Python 中等待 Windows 文件 I/O 完成
【发布时间】:2014-03-09 00:05:30
【问题描述】:

我有一组系统测试,它们会启动一些进程、创建文件等,然后将它们全部关闭并删除文件。

我在清理时遇到两个间歇性错误:

在由其中一个进程创建的日志文件上:

    os.remove(log_path)
WindowsError: [Error 32] The process cannot access the file because it is being used by another process: <path_to_file>

尝试使用shutil.rmtree 删除输出目录时:

File "C:\Python27\lib\shutil.py", line 254, in rmtree
    os.rmdir(path)
WindowsError: [Error 145] The directory is not empty: 'C:\\TestTarget\\xxx'

如果我在整理之前插入 2 秒延迟,这两个错误都会消失,所以我认为问题在于 Windows 释放文件所需的时间。显然我想避免延迟测试,有没有办法等到文件系统赶上?

【问题讨论】:

  • 你可以在一个循环中插入一个try 块并循环直到它成功......这行得通吗?
  • 这是一个合理的权宜之计,谢谢。如果有的话,我想要一个更清洁的解决方案。
  • 我认为只要进程在关闭时正确关闭文件,应该可以立即删除。您可能会寻找问题的真正原因。 :-)
  • 我也遇到过类似的问题。我认为这要么是防病毒软件的问题,要么是 NTFS 中的错误。根据我的经验,它通常会很快解决,因此最简单的解决方法是检测故障,短暂延迟(可能 10 毫秒),然后循环重试。
  • 这里有同样的问题。我正在删除一个目录 shutil.rmtree(),然后使用 os.rename() 将另一个目录重命名为相同的目录,并收到错误“当该文件已存在时无法创建文件”。在我看来有点荒谬,我正在尝试使用 python 作为跨平台的 shell/batch 替换,而且我绝对从未在 shell 或批处理脚本中看到过这种类型的问题。

标签: python windows


【解决方案1】:

我遇到了类似的问题,我花了几个月的时间寻找合适的解决方案,但一无所获。对我来说,这个问题只发生在使用 python2.7 在 Windows 上运行我的脚本时。在python3上大部分时间都没有问题。在 GNU/Linux 上,我可以在没有这种肮脏解决方案的情况下使用文件操作。

我最终将这个函数用于 Windows 的任何文件操作:try_fail_wait_repeat(见下文),你应该做类似的事情。您也可以将睡眠设置为不同的值。

import sys
import shutil
import time
import os

IS_WINDOWS = (sys.platform == "win32")


if IS_WINDOWS:
    maximum_number_of_tries = 40
    def move_folder(src, dst): 
        return try_fail_wait_repeat(maximum_number_of_tries, _move_dir, src, dst)
    def read_file(path): 
        return try_fail_wait_repeat(maximum_number_of_tries, _read_file, path)
else:
    def move_folder(src, dst):
        return shutil.move(src, dst)
    
    def read_file(path):
        return _read_file(path)


def _read_file(file_path):
    with open(file_path, "rb") as f_in:
        data = f_in.read().decode("ISO-8859-1")
    return data


def try_fail_wait_repeat(maximum_number_of_tries, func, *args):
    """A dirty solution for a dirty bug in windows python2"""
    i = 0
    while True:
        try:
            res = func(*list(args))
            return res
        except WindowsError as e:
            i += 1
            time.sleep(0.5)
            if i > maximum_number_of_tries:
                print("Too much trying to run {}({})".format(func, args))
                raise e

【讨论】:

    【解决方案2】:

    你使用的函数只删除空目录

    尝试:

    import shutil
    shutil.rmtree('/folder_path')
    

    另外,请尝试在关闭进程之前添加睡眠间隔。

    【讨论】:

    • 我发现 rmtree 调用 os.rmdir(path) 并且仍然给出相同的错误。 ```clear_directory 中的 clear_directory() shutil.rmtree(download_dir) 文件“C:\python27_x64\lib\shutil.py”,第 247 行,在 rmtree rmtree(fullname, ignore_errors, onerror) 文件“C:\python27_x64\lib\ shutil.py",第 256 行,在 rmtree onerror(os.rmdir, path, sys.exc_info()) 文件 "C:\python27_x64\lib\shutil.py",第 254 行,在 rmtree os.rmdir(path) WindowsError : [错误 145] 目录不为空: 'D:\\downloads\\test' '''
    猜你喜欢
    • 2023-03-18
    • 2012-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多