问题
I want to do something like:
import csv
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def post(self):
uploaded_csv_file = self.request.files['file'][0]
with uploaded_csv_file as csv_file:
for row in csv.reader(csv_file):
self.write(' , '.join(row))
But, uploaded_csv_file
is not of type file
.
What is the best practice here?
Sources:
- http://docs.python.org/2/library/csv.html
- http://docs.python.org/2/library/functions.html#open
- https://stackoverflow.com/a/11911972/242933
回答1:
As the documentation explains:
csvfile
can be any object which supports the iterator protocol and returns a string each time itsnext()
method is called — file objects and list objects are both suitable.
So, if you have something which is not a file, but is an iterator over lines, that's fine. If it's not even an iterator over lines, just wrap it in one. For a trivial example, if it's something with a read_all()
method, you can always do this:
uploaded_csv_file = self.request.files['file'][0]
contents = uploaded_csv_file.read_all()
lines = contents.splitlines()
for row in csv.reader(lines):
# ...
(Obviously you can merge steps together to make it briefer; I just wrote each step as a separate line to make it simpler to understand.)
Of course if the CSV files are large, and especially if they take a while to arrive and you've got a nice streaming interface, you probably don't want to read the whole thing at once this way. Most network server frameworks offer nice protocol adapters to, e.g., take a stream of bytes and give you a stream of lines. (For that matter, even socket.makefile()
in the stdlib sort of does that…) But in your case, I don't think that's an issue.
来源:https://stackoverflow.com/questions/18069856/tornado-read-uploaded-csv-file