使用 os.remove() 时,每 10000 次左右就有 1 次出现 PermissionError

1 in every 10000 times or so I get a PermissionError when using os.remove()

我写了一个脚本,从视频中提取帧以获取一些信息,所以我遍历帧,将图像写入临时文件夹,进行一些操作,删除图像:

# if frame exists, capture 
while framesleft:
    framesleft,image = vid.read()
    if framesleft:
        imfile = cv2.imwrite("temperonispaghettioni/video%03dframe%05d.png" % (videonr, framenr), image)

        # write the filename, video and frame to FrameList.csv
        row = ["bla bla bla unimportant stuff"]
        writer.writerow(row)  

        # Make sure the image is closed and remove the image     
        image = None
        imfile = None
        os.remove("temperonispaghettioni/video%03dframe%05d.png" % (videonr, framenr))

大多数情况下这一切都很好。每 10000 次左右的迭代一次,不是一个确切的数字并且它会变化,我得到以下错误:

    os.remove("temperonispaghettioni/video%03dframe%05d.png" % (videonr, framenr))

PermissionError: [WinError 5] Access is denied: 'temperonispaghettioni/video000frame01218.png'

如您所见,我尝试将 image 和 imfile 设置为 None 以尝试关闭文件。这似乎并不能解决问题。我还可以尝试如何正确关闭文件,还是这里有其他问题?

还有我的 while framesleft: if framesleft: 是一种低效的方法,我意识到这一点。我遇到的问题是,当视频失帧时,代码会创建 1 个我无法处理的最后损坏的 .png。如果有人有改进建议,我们将非常欢迎。

编辑: 我已经尝试捕获原始错误:

try:
    os.remove("temperonispaghettioni/video%03dframe%05d.png" % (videonr, framenr))
except PermissionError:
    print('Ran into an error with deleting frame %05d of video %03d, trying again...' %(framenr,videonr))
    time.sleep(0.5)
    try:
        os.remove("temperonispaghettioni/video%03dframe%05d.png" % (videonr, framenr))
        print('Succesfully removed frame%05d of video %03d, moving on...' %(framenr,videonr))
    except PermissionError:
        print('Removal failed, frame will remain in the folder and the folder won\'t delete itself. Moving on...')

我已经将整个脚本循环到 运行 几百次以查看是否可以重新创建错误,到目前为止它甚至没有进入 except 阶段,但我遇到了一个新错误:

 os.mkdir('temperonispaghettioni')

PermissionError: [WinError 5] Access is denied: 'temperonispaghettioni'

同样的问题,但现在是制作目录。我应该尝试捕获每个 writing/deleting 操作吗?

你这里的构造需要一个中间循环中断:

while True:
    framesleft, image = vid.read()
    if not framesleft:
        break
    process(framesleft, image)

另一种方式,如果你不介意重复一点点,你也可以在循环外进行第一次读取:

framesleft, image = vid.read()
while framesleft:
    process(framesleft, image)
    framesleft, image = vid.read()

在 Python 3.8 之前,这些确实是在 Python.

中编写那种循环的唯一方法

在 Python 3.8 及更高版本中,Python 获得了人们一直称之为海象运算符的新赋值表达式语法::=。使用海象运算符,您可以改为执行以下操作:

while (frame_image := vid.read())[0]:
    framesleft, image = frame_image
    process(framesleft, image)

至于为什么你会收到权限被拒绝的错误,我真的不能说,你的 post 中没有足够的信息来真正了解这里发生了什么。在启动程序之前,您是否确保该目录是空的,并且没有以前运行的可能具有不正确权限的剩余文件?您是否在后台或单独的 thread/process 中有程序 运行 的另一个实例?

此外,由于您创建文件只是为了事后删除它,为什么不直接使用 https://docs.python.org/3.7/library/tempfile.html#tempfile.mkstemp 这样您就不必生成唯一的文件名并祈祷没有冲突或权限问题。