保存图像fi时在Flask中获取错误“ValueError:读取关闭的文件”

2024-06-16 13:47:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个flask应用程序,从上传的jpeg文件中读取元数据。然后将文本写入元数据文件。我一直收到一个错误,我正在读一个关闭的文件,但它我知道我正在打开文件。在

我有一个python脚本,它成功地从文件夹中的所有文件中读取元数据并将其写入文件。但是当我把代码放到一个flask应用程序中时,我得到了一个错误。在

我的flask应用程序有一个python文件:

在应用程序副本公司名称:

import PIL
import PIL.Image
import PIL.ExifTags
import pandas
import os
from os import path
import shutil
import json
import requests
import datetime
from datetime import datetime
from datetime import timedelta
from flask import Flask , render_template, request

app = Flask(__name__)

a = datetime(1970,1,1,0,1,1)

api_token = 'donotputactualkey'
api_url_base = 'https://api.darksky.net/forecast/'

APP_ROOT = os.path.dirname(os.path.abspath(__file__))

LOG_ROOT = os.path.join(APP_ROOT,'logs')
if not os.path.isdir(LOG_ROOT):
    os.mkdir(LOG_ROOT)


if not path.isfile('logs/ErrorLog.txt'):
    err = open('logs/ErrorLog.txt','a')
    err.write('FileName, ErrorDesc,DateTime \n')
    err.close()
else:
    err = open('logs/ErrorLog.txt','a')



if not path.isfile('logs/PhotoLatLong.txt'):
    log = open('logs/PhotoLatLong.txt','a')
    log.write('FileName,DateTaken,Lat,Long,precipIntensity,PrecipProbability,temperature,apparentTemperature,dewPoint,humidity,pressure,windSpeed,windGust,windBearing,CloudCover,uvIndex,visibility,nearest-station \n')
    log.close()
else:
    log = open('logs/PhotoLatLong.txt','a')


@app.route('/')
def index():
    return render_template('upload.html')

@app.route('/upload', methods = ['GET','POST'])
def upload():
    target = os.path.join(APP_ROOT,'images/')
    print(target)

    if not os.path.isdir(target):
        os.mkdir(target)
    CurDate = str(datetime.now()).split('.')[0]
    if err.closed:
        open(err)
    if log.closed:
        open(log)
    for file in request.files.getlist('file'):
        FileName = file.name
        print(FileName)
        img = PIL.Image.open(file)
        exif_data = img._getexif()
        if 306 not in exif_data.keys():
            print(str(File)+' has no datetime stamp')
            err.write(str(FileName+', No Date found,'+CurDate+'\n'))
            err.close()
        else:
            DateTaken =   exif_data[306]
            ApiDate = DateTaken[:4]+'-'+DateTaken[5:7]+'-'+DateTaken[8:10]+'T'+DateTaken[11:19]
            FileDate = DateTaken[:4]+'-'+DateTaken[5:7]+'-'+DateTaken[8:10]+' '+DateTaken[11:19]
            b = datetime(int(DateTaken[:4]),int(DateTaken[5:7]),int(DateTaken[8:10]),int(DateTaken[11:13]),int(DateTaken[14:16]),int(DateTaken[17:20]))
            newval = exif_data.get(34853)
        if 2 not in newval:
            err.write(str(str(FileName) +', GPS info not found,'+str(datetime.now()).split('.')[0]+'\n'))
            err.close()
        else:
            latdegs = exif_data[34853][2][0][0]
            latmins = exif_data[34853][2][1][0]
            latsecs = exif_data[34853][2][2][0]  / exif_data[34853][2][2][1]
            latcoords = latdegs + latmins/60 + latsecs/3600
            longdegs = exif_data[34853][4][0][0]
            longmins = exif_data[34853][4][1][0]
            longsecs = exif_data[34853][4][2][0]  / exif_data[34853][4][2][1]
            longcoords = longdegs + longmins/60 + longsecs/3600
            longcoords = longcoords * -1
            api_url_latlon = str(latcoords) +','+str(longcoords)
            time = ',' +ApiDate
            response = requests.get(api_url_base+api_token+'/'+api_url_latlon+time)
            dataapi = json.loads(response.content.decode('utf-8'))
            TT = (b-a).total_seconds()
            T1 = dataapi['hourly']['data'][0]['time']
            T2 = dataapi['hourly']['data'][1]['time']
            T3 = dataapi['hourly']['data'][2]['time']
            T4 = dataapi['hourly']['data'][3]['time']
            T5 = dataapi['hourly']['data'][4]['time']
            d = {0:TT-T1, 1:TT-T2, 2:TT-T3, 3:TT-T4, 4:TT-T5}
            k = min(d.items(),key=lambda x: x[1])
            pi = str(dataapi['hourly']['data'][k[0]]['precipIntensity'])
            pp = str(dataapi['hourly']['data'][k[0]]['precipProbability'])
            t = str(dataapi['hourly']['data'][k[0]]['temperature'])
            at = str(dataapi['hourly']['data'][k[0]]['apparentTemperature'])
            dp = str(dataapi['hourly']['data'][k[0]]['dewPoint'])
            hum = str(dataapi['hourly']['data'][k[0]]['humidity'])
            pr = str(dataapi['hourly']['data'][k[0]]['pressure'])
            ws = str(dataapi['hourly']['data'][k[0]]['windSpeed'])
            wg = str(dataapi['hourly']['data'][k[0]]['windGust'])
            wb = str(dataapi['hourly']['data'][k[0]]['windBearing'])
            cc = str(dataapi['hourly']['data'][k[0]]['cloudCover'])
            uv = str(dataapi['hourly']['data'][k[0]]['uvIndex'])
            vi = str(dataapi['hourly']['data'][k[0]]['visibility'])
            log.write(str(str(FileName) +','+str(FileDate)+','+str(latcoords)+','+str(longcoords)+','+pi+','+pp+','+t+','+at+','+dp+','+hum+','+pr+','+ws+','+wb+','+cc+','+uv+','+vi+'\n') )
            img.close()
            log.close()

        print(file)
        filename = file.filename
        destination = '/'.join([target, filename])
        print(destination)
        file.save(destination)

    return render_template('complete.html')


if __name__ == "__main__":
    app.run(debug = True)

希望被重定向到'完整.html'但控制台显示以下错误:

^{pr2}$

Tags: pathimportlogapidatadatetimeifos
1条回答
网友
1楼 · 发布于 2024-06-16 13:47:57

这是因为您已经用PIL关闭了底层file对象:

for file in request.files.getlist('file'):
    FileName = file.name
    print(FileName)
    img = PIL.Image.open(file)
    ...
    else:
        ...
        img.close() # <    

    # At this point, the file object is already closed.
    file.save(destination)

尝试删除获取filefile.save之间的所有图像元数据处理代码,它应该会成功。在

^{pr2}$

Image.close() docs

Closes the file pointer, if possible.

This operation will destroy the image core and release its memory. The image data will be unusable afterward.

这会影响来自request.files^{} object,它本身只是底层file对象的包装器。在

因为不管for循环中的图像元数据提取发生了什么,都会保存图像文件,所以只需将其移到for循环的开始。在

for file in request.files.getlist('file'):
    filename = file.filename
    destination = '/'.join([target, filename])
    file.save(destination)

    FileName = file.name
    img = PIL.Image.open(file)
    # proceed with image data extraction
    ...

    # do not forget to close
    img.close() 

相关问题 更多 >