2

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:

Community
  • 1
  • 1
ma11hew28
  • 121,420
  • 116
  • 450
  • 651

1 Answers1

1

As the documentation explains:

csvfile can be any object which supports the iterator protocol and returns a string each time its next() 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.

abarnert
  • 354,177
  • 51
  • 601
  • 671