Reputation: 2939
I am attempting to return a zip of pandas data frames within my Flask app. I have one of my views return the output from the serve_csv function. This is the original serve_csv function that I had, which successfully downloads a specified csv.
def serve_csv(dataframe,filename):
buffer = StringIO.StringIO()
dataframe.to_csv(buffer, encoding='utf-8', index=False)
buffer.seek(0)
return send_file(buffer,
attachment_filename=filename,
mimetype='text/csv')
I am attempting to change it to a serve_zip function that takes a list of pandas data frames and returns a zip of the corresponding csv files. However, I am receiving an error that states that an object of type Nonetype has no len. I am guessing this has to do with how I am attempting to write to the buffer, but after reading the documentation, am not sure how to fix it. Here is my current function:
def serve_zip(data_list,filename):
'''data_list: a list of pandas data frames
filename'''
zipped_file = StringIO.StringIO()
with zipfile.ZipFile(zipped_file, 'w') as zip:
for i, dataframe in enumerate(data_list):
print type(dataframe.to_csv(zipped_file, encoding='utf-8', index=False))
zip.writestr(filename, dataframe.to_csv(zipped_file, encoding='utf-8', index=False))
zipped_file.seek(0)
return send_file(zipped_file,
attachment_filename=filename,
mimetype='application/octet-stream')
And my stack trace:
Full traceback:
127.0.0.1 - - [17/Feb/2015 15:57:21] "POST /part2/ HTTP/1.1" 500 -
Traceback (most recent call last):
File "/private/var/folders/f4/qr09tm_169n4b9xyjsrjv8680000gn/T/tmpmQ95cJ/.deps/Flask-0.10.1-py2.7.egg/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/private/var/folders/f4/qr09tm_169n4b9xyjsrjv8680000gn/T/tmpmQ95cJ/.deps/Flask-0.10.1-py2.7.egg/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/private/var/folders/f4/qr09tm_169n4b9xyjsrjv8680000gn/T/tmpmQ95cJ/.deps/Flask-0.10.1-py2.7.egg/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/private/var/folders/f4/qr09tm_169n4b9xyjsrjv8680000gn/T/tmpmQ95cJ/.deps/Flask-0.10.1-py2.7.egg/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/private/var/folders/f4/qr09tm_169n4b9xyjsrjv8680000gn/T/tmpmQ95cJ/.deps/Flask-0.10.1-py2.7.egg/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/private/var/folders/f4/qr09tm_169n4b9xyjsrjv8680000gn/T/tmpmQ95cJ/.deps/Flask-0.10.1-py2.7.egg/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/private/var/folders/f4/qr09tm_169n4b9xyjsrjv8680000gn/T/tmpmQ95cJ/.deps/Flask-0.10.1-py2.7.egg/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/private/var/folders/f4/qr09tm_169n4b9xyjsrjv8680000gn/T/tmpmQ95cJ/.deps/Flask-0.10.1-py2.7.egg/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/private/var/folders/f4/qr09tm_169n4b9xyjsrjv8680000gn/T/tmpmQ95cJ/webapp.py", line 110, in part2
return serve_zip([table3, agg_table], 'my_file.csv')
File "/private/var/folders/f4/qr09tm_169n4b9xyjsrjv8680000gn/T/tmpmQ95cJ/webapp.py", line 61, in serve_csv
zip.writestr(filename, dataframe.to_csv(zipped_file, encoding='utf-8', index=False))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/zipfile.py", line 1216, in writestr
zinfo.file_size = len(bytes) # Uncompressed size
TypeError: object of type 'NoneType' has no len()
127.0.0.1 - - [17/Feb/2015 15:57:21] code 400, message Bad request version ('RTSP/1.0')
127.0.0.1 - - [17/Feb/2015 15:57:21] "GET /info?txtAirPlay&txtRAOP RTSP/1.0" 400 -
127.0.0.1 - - [17/Feb/2015 15:57:21] "GET /part2/?__debugger__=yes&cmd=resource&f=style.css HTTP/1.1" 200 -
127.0.0.1 - - [17/Feb/2015 15:57:21] "GET /part2/?__debugger__=yes&cmd=resource&f=jquery.js HTTP/1.1" 200 -
127.0.0.1 - - [17/Feb/2015 15:57:21] "GET /part2/?__debugger__=yes&cmd=resource&f=debugger.js HTTP/1.1" 200 -
127.0.0.1 - - [17/Feb/2015 15:57:21] "GET /part2/?__debugger__=yes&cmd=resource&f=ubuntu.ttf HTTP/1.1" 200 -
127.0.0.1 - - [17/Feb/2015 15:57:21] "GET /part2/?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 -
127.0.0.1 - - [17/Feb/2015 15:57:21] "GET /part2/?__debugger__=yes&cmd=resource&f=source.png HTTP/1.1" 200 -
127.0.0.1 - - [17/Feb/2015 15:57:21] "GET /part2/?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 -
Upvotes: 0
Views: 1497
Reputation: 159865
It looks like dataframe.to_csv
doesn't return the string if a buffer object is provided, but writes the CSV data into the buffer. This is not what you want to do anyway, since you want the data in the buffer to be a valid zip file. Instead, pass in None
:
zip.writestr(filename, dataframe.to_csv(None, encoding='utf-8', index=False))
This way the zip object will compress the CSV string and add it to the zip archive (which you are buffering in memory via StringIO
).
Upvotes: 2