我正在尝试使用以下命令删除临时文件:
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
我不确定为什么它适用于图像而不适用于f。
答案 0 :(得分:7)
您正在尝试使用文件对象,而不是文件名。使用os.remove(f.name)
或使用os.remove(tmpfn)
。
您还希望切换到使用文件作为上下文管理器(使用with
语句),以便它们自动关闭,并且tempfile
module也可能对您感兴趣。
使用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
,而不是之前。
答案 1 :(得分:1)
FWIW,其中一个问题是由于PIL的错误造成。
如果你在非图像文件上执行Image.open(filename)
,它会引发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