0

我正在尝试使用以下方法删除临时文件:

os.remove(str('temp.bin'))

这是完整的功能,请注意我正在使用 API (XWF) 将数据读入文件,它可以正常工作。当它接收到有效图像时,它工作正常,因此问题不在此关闭范围之内。该代码仅在收到无效图像文件时才会出现问题。我将输入读入临时文件,因为它适用于我的解决方案,这里的问题是当它们不是有效图像时它不会删除它们。我不是在寻找关于为什么在将图像写入临时文件之前检测它是否是图像会更好的讲座。幽默我,现在假设我这样做是有充分理由的。

import OutputRedirector
import XWF
import os
from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS

gps_data = {}

def XT_ProcessItemEx(nItem, hItem, reserved):
    global gps_data
    fn = XWF.GetItemName(nItem)
    offset = 0
    size = XWF.GetItemSize(nItem)
    if offset < size:
        tempfn = fn + '.bin'
        f = open(tempfn, 'wb')
        buffer = XWF.Read(hItem, offset, size)
        f.write(buffer)
        f.close()
        try:
            image = Image.open(tempfn)
            exif_data = get_exif_data(image)
            gps = get_lat_lon(exif_data)
            if gps[0]:
                gps_data[fn] = (repr(gps[0]), repr(gps[1]))
                print('Found GPS data in %s' % fn)
            else:
                print('No GPS data in image %s' % fn)
            del image
            os.remove(str(tempfn)) # it works fine here
        except IOError:
            print('Not an image')
            os.remove(str(f)) # but it won't work here
    else:
        print('File too small')
    return

如果我不按原样保留该行并且不使用 str() 附件,我会收到此错误:

TypeError :  must be string, not file 

正如我得到这个错误:

WindowsError :  [Error 123] The filename, directory name, or volume 
label syntax is incorrect: "<closed file u'file.pdf.bin', 
mode 'wb' at 0x0A82A0D0>" 

如果我在函数/方法根级别返回之前直接移动有问题的行,我会收到此错误:

WindowsError :  [Error 32] The process cannot access the file because 
it is being used by another process

我不确定为什么它适用于 image 但不适用于 f。

4

2 回答 2

7

您正在尝试使用文件对象,而不是文件名。使用os.remove(f.name)或使用os.remove(tmpfn).

您还想切换到使用文件作为上下文管理器(使用with语句),以便它们自动关闭,并且您可能也对tempfile模块感兴趣。

使用with

with open(tempfn, 'wb') as f:
    buffer = XWF.Read(hItem, offset, size)
    f.write(buffer)

(注意f.close()这里的省略。

使用tempfile; 关闭时TemporaryFile自动清理:

from tempfile import TemporaryFile


with TemporaryFile(prefix=fn) as tmpfile:
    tmpfile.write(XWF.Read(hItem, offset, size))
    tmpfile.seek(0)
    try:
        image = Image.open(tmpfile)
        exif_data = get_exif_data(image)
    except IOError:
        print 'Not an image'
        return

    gps = get_lat_lon(exif_data)
    if gps[0]:
        gps_data[fn] = (repr(gps[0]), repr(gps[1]))
        print('Found GPS data in %s' % fn)
    else:
        print('No GPS data in image %s' % fn)

    del image

 # tmpfile is automatically closed because we used it as a context manager

您还希望最小化放入try块中的内容,仅在实际读取图像数据时捕获IOError,而不是之前。

于 2013-05-23T18:50:07.337 回答
1

FWIW,问题之一是由于 PIL 的错误特征。

如果您Image.open(filename)对非图像文件执行 an ,它会引发 an IOError,但不会关闭打开的文件,这有点顽皮......

>>> import os
>>> from PIL import Image
>>> i = Image.open('something.bin')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Progra~1\Python\lib\site-packages\PIL\Image.py", line 1980, in open
    raise IOError("cannot identify image file")
IOError: cannot identify image file
>>> os.remove('something.bin')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
WindowsError: [Error 32] The process cannot access the file because it is being used by another process: 'something.bin'

您可以通过给它一个文件对象来解决它...

filename = 'something.bin'
f = open(filename, 'rb')
try:
    i = Image.open(f)
    # do the thing
except IOError:
   f.close()
   os.remove(filename)

但是,如果您已经将所有图像数据加载到 RAM 中,那么创建临时文件似乎没有多大意义。你可以只使用一个StringIO...

from cStringIO import StringIO

def XT_ProcessItemEx(nItem, hItem, reserved):
    global gps_data
    fn = XWF.GetItemName(nItem)
    offset = 0
    size = XWF.GetItemSize(nItem)
    if offset < size:
        buffer = XWF.Read(hItem, offset, size)
        sio = StringIO(buffer)
        try:
            image = Image.open(sio)
            exif_data = get_exif_data(image)
            gps = get_lat_lon(exif_data)
            if gps[0]:
                gps_data[fn] = (repr(gps[0]), repr(gps[1]))
                print('Found GPS data in %s' % fn)
            else:
                print('No GPS data in image %s' % fn)
        except IOError:
            print('Not an image')
    else:
        print('File too small')
    return
于 2013-05-23T19:20:53.020 回答