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

イメージでは機能するのに 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、問題の 1 つは 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
于 2013-05-23T19:20:53.020 に答える