16

I am reading csv file through upload and trying to store all values in a list

def upload(request):
    paramFile = request.FILES['file'].read()
    data = csv.DictReader(paramFile)
    list1 = []
    for row in data:
        list1.append(row)

    print list1

file.csv

12345,abcdef

output

[{'1': '', None: ['']}, {'1': '2'}]

I want to append all values in list1

6
  • What is your expected output? Is it [{12345: 'abcdef'}]? Commented Jul 11, 2014 at 19:02
  • And? What's the question here? Commented Jul 11, 2014 at 19:04
  • i want final list to be as list1 = ['12345', 'abcdef'] Commented Jul 11, 2014 at 19:04
  • 1
    I see nothing having to do with dictionaries, so why are you using DictReader? Commented Jul 11, 2014 at 19:05
  • @shashisp are you sure you don't want a list of lists: [['12345', 'abcdef'], ...]? One for each line in the CSV? Commented Jul 11, 2014 at 19:16

3 Answers 3

50

This should work if you're using Python 3.

file = request.FILES['file'] 
decoded_file = file.read().decode('utf-8').splitlines()
reader = csv.DictReader(decoded_file)
for row in reader:
    # Get each cell value based on key-value pair. 
    # Key will always be what lies on the first row.

We can use the list that splitlines() creates. splitlines() is called because csv.DictReader expects "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".

Sign up to request clarification or add additional context in comments.

3 Comments

nice note on the decoded_file variable. This had me stumped all afternoon and that line helped, thanks!
If you're trying to read some CSV inside a django model textarea, splitlines() will also do the trick!
This appears to leave the file open if you're adapting this solution to read an uploaded file off the filesystem. Might want to use this in that case: ` ... with file.open() as buffer: decoded_file = buffer.read().decode('utf-8').splitlines() ... `
17

in Python 3, to get the correct type (String not bytes) without reading the full file into memory you can use a generator to decode line by line:

def decode_utf8(input_iterator):
    for l in input_iterator:
        yield l.decode('utf-8')

def upload(request):
    reader = csv.DictReader(decode_utf8(request.FILES['file']))
    for row in reader:
        print(row)

2 Comments

Or using generator expression: reader = csv.DictReader(chunk.decode() for chunk in request.FILES['file'])
What if the chunking algorithm splits apart a multi-byte UTF-8 character? This would cause a UnicodeDecodeError.
7

You have two problems:

  • You are passing a string to the constructor of DictReader. You must pass an iterable object that gives the individual lines in the input (a string is iterable, but will give each character one at a time). Luckily, an UploadedFile object (like those in the FILES dictionary) are already file-like objects that support iteration, so just do this:

    data = csv.DictReader(request.FILES['file'])
    
  • Your input data only has one line. DictReader will use that line for the column "headers", which will become the key in the resulting dictionaries. You will then have no data left! It looks like you don't want a DictReader, just a regualar reader:

    data = csv.reader(request.FILES['file'])
    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.