我有一个flask应用程序,正在从上载的jpeg文件中读取元数据。然后,它将元数据写入文本文件。我不断收到我正在读取已关闭文件的错误,但我知道我正在打开文件。
我有一个python脚本,可以成功从文件夹中的所有文件读取元数据并将其写入文件。但是,当我将该代码放入Flask应用程序中时,我得到了错误。
我的烧瓶应用程序具有一个python文件:
app.py:
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)
期望被重定向到“ complete.html”,但控制台显示此错误:
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: on
* Restarting with stat
* Debugger is active!
* Debugger PIN: 964-871-100
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
C:\Users\denjs\Documents\UdemyFlaskReview\PicUpload\images/
file
<FileStorage: 'P5040063.JPG' ('image/jpeg')>
C:\Users\denjs\Documents\UdemyFlaskReview\PicUpload\images//P5040063.JPG
127.0.0.1 - - [16/Aug/2019 13:39:02] "POST /upload HTTP/1.1" 500 -
Traceback (most recent call last):
File "C:\Users\denjs\AppData\Local\conda\conda\envs\mynewflaskenv\lib\site-packages\flask\app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "C:\Users\denjs\AppData\Local\conda\conda\envs\mynewflaskenv\lib\site-packages\flask\app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "C:\Users\denjs\AppData\Local\conda\conda\envs\mynewflaskenv\lib\site-packages\flask\app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "C:\Users\denjs\AppData\Local\conda\conda\envs\mynewflaskenv\lib\site-packages\flask\_compat.py", line 35, in reraise
raise value
File "C:\Users\denjs\AppData\Local\conda\conda\envs\mynewflaskenv\lib\site-packages\flask\app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "C:\Users\denjs\AppData\Local\conda\conda\envs\mynewflaskenv\lib\site-packages\flask\app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Users\denjs\AppData\Local\conda\conda\envs\mynewflaskenv\lib\site-packages\flask\app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Users\denjs\AppData\Local\conda\conda\envs\mynewflaskenv\lib\site-packages\flask\_compat.py", line 35, in reraise
raise value
File "C:\Users\denjs\AppData\Local\conda\conda\envs\mynewflaskenv\lib\site-packages\flask\app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\denjs\AppData\Local\conda\conda\envs\mynewflaskenv\lib\site-packages\flask\app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\denjs\Documents\UdemyFlaskReview\PicUpload\app.py", line 123, in upload
file.save(destination)
File "C:\Users\denjs\AppData\Local\conda\conda\envs\mynewflaskenv\lib\site-packages\werkzeug\datastructures.py", line 2728, in save
copyfileobj(self.stream, dst, buffer_size)
File "C:\Users\denjs\AppData\Local\conda\conda\envs\mynewflaskenv\lib\shutil.py", line 79, in copyfileobj
buf = fsrc.read(length)
File "C:\Users\denjs\AppData\Local\conda\conda\envs\mynewflaskenv\lib\tempfile.py", line 740, in read
return self._file.read(*args)
File "C:\Users\denjs\AppData\Local\conda\conda\envs\mynewflaskenv\lib\tempfile.py", line 485, in func_wrapper
return func(*args, **kwargs)
ValueError: read of closed file
127.0.0.1 - - [16/Aug/2019 13:39:02] "GET /upload?__debugger__=yes&cmd=resource&f=style.css HTTP/1.1" 200 -
127.0.0.1 - - [16/Aug/2019 13:39:02] "GET /upload?__debugger__=yes&cmd=resource&f=debugger.js HTTP/1.1" 200 -
127.0.0.1 - - [16/Aug/2019 13:39:02] "GET /upload?__debugger__=yes&cmd=resource&f=jquery.js HTTP/1.1" 200 -
127.0.0.1 - - [16/Aug/2019 13:39:02] "GET /upload?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 -
127.0.0.1 - - [16/Aug/2019 13:39:02] "GET /upload?__debugger__=yes&cmd=resource&f=ubuntu.ttf HTTP/1.1" 200 -
答案 0 :(得分:1)
这是因为您已经使用PIL关闭了基础文件对象:
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)
尝试在获取file
和file.save
之间删除所有图像元数据处理代码,它应该会成功。
for file in request.files.getlist('file'):
destination = '/'.join([target, filename])
file.save(destination)
如果可能,关闭文件指针。
此操作将破坏图像核心并释放其内存。的 图片数据以后将无法使用。
这会影响request.files
中的FileStorage
object,后者本身只是基础文件对象的包装。
由于无论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()