2

So i have a list:

>>> print references
>>> ['Reference xxx-xxx-xxx-007 ', 'Reference xxx-xxx-xxx-001 ', 'Reference xxx-xxx-xxxx-00-398 ', 'Reference xxx-xxx-xxxx-00-399']

(The list is much longer than that)

I need to write a CSV file wich would look this:

Column 1:
Reference xxx-xxx-xxx-007
Reference xxx-xxx-xxx-001
[...]

I tried this :

c = csv.writer(open("file.csv", 'w'))
for item in references:
    c.writerows(item)
Or:
for i in range(0,len(references)):
    c.writerow(references[i])

But when I open the csv file created, I get a window asking me to choose the delimiter No matter what, I have something like R,e,f,e,r,e,n,c,es

4
  • How do you want your output to look like? What are the rules? Commented Feb 6, 2013 at 9:46
  • I don't know the library you use, but did you try c.writerows(references) (instead of the for loop) ? Commented Feb 6, 2013 at 9:46
  • 1
    @Fabien: The csv library comes with Python; you should know it. Commented Feb 6, 2013 at 9:50
  • @abarnert didn't know that was in the default libs ; thanks for the information. Commented Feb 6, 2013 at 10:10

3 Answers 3

5

writerows takes a sequence of rows, each of which is a sequence of columns, and writes them out.

But you only have a single list of values. So, you want:

for item in references:
    c.writerow([item])

Or, if you want a one-liner:

c.writerows([item] for item in references)

The point is, each row has to be a sequence; as it is, each row is just a single string.

So, why are you getting R,e,f,e,r,e,n,c,e,… instead of an error? Well, a string is a sequence of characters (each of which is itself a string). So, if you try to treat "Reference" as a sequence, it's the same as ['R', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e'].


In a comment, you asked:

Now what if I want to write something in the second column ?

Well, then each row has to be a list of two items. For example, let's say you had this:

references = ['Reference xxx-xxx-xxx-007 ', 'Reference xxx-xxx-xxx-001 ']
descriptions = ['shiny thingy', 'dull thingy']

You could do this:

csv.writerows(zip(references, descriptions))

Or, if you had this:

references = ['Reference xxx-xxx-xxx-007 ', 'Reference xxx-xxx-xxx-001 ', 'Reference xxx-xxx-xxx-001 ']
descriptions = {'Reference xxx-xxx-xxx-007 ': 'shiny thingy', 
                'Reference xxx-xxx-xxx-001 ': 'dull thingy']}

You could do this:

csv.writerows((reference, descriptions[reference]) for reference in references)

The key is, find a way to create that list of lists—if you can't figure it out all in your head, you can print all the intermediate steps to see what they look like—and then you can call writerows. If you can only figure out how to create each single row one at a time, use a loop and call writerow on each row.


But what if you get the first column values, and then later get the second column values?

Well, you can't add a column to a CSV; you can only write by row, not column by column. But there are a few ways around that.

First, you can just write the table in transposed order:

c.writerow(references)
c.writerow(descriptions)

Then, after you import it into Excel, just transpose it back.

Second, instead of writing the values as you get them, gather them up into a list, and write everything at the end. Something like this:

rows=[[item] for item in references] 
# now rows is a 1-column table
# ... later
for i, description in enumerate(descriptions):
    values[i].append(description)
# and now rows is a 2-column table
c.writerows(rows)

If worst comes to worst, you can always write the CSV, then read it back and write a new one to add the column:

with open('temp.csv', 'w') as temp:
    writer=csv.writer(temp)
    # write out the references
# later
with open('temp.csv') as temp, open('real.csv', 'w') as f:
    reader=csv.reader(temp)
    writer=csv.writer(f)
    writer.writerows(row + [description] for (row, description) in zip(reader, descriptions))
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you, the second option works perfectly. Each reference is in a row. Now what if I want to write something in the second column ?
@Yanis: Then you just create a list of lists of two items each, instead of a list of lists of one item each. Let me add an example to the answer.
EDIT: OK got it ! csv.writerows(zip(references, descriptions)) zip ?
You can't write one column, then the next column; you have to write one row, then the next row. But… let me edit the answer again.
@Yanis: Exactly! What's the question at the end for? Do you not know what zip does? Play with it in the interactive interpreter, or print out the intermediate results from your script; you'll get the idea pretty quickly. (One caveat: If you're using Python 3.x, you'll want to print list(zip(x, y)), not just zip(x, y). Try it both ways and you'll see why you need to convert to a list.)
|
1

writerow writes the elements of an iterable in different columns. This means that if your provide a tuple, each element will go in one column. If you provide a String, each letter will go in one column. If you want all the content in the same column do the following:

c = csv.writer(open("file.csv", 'wb'))
c.writerows(references)

or

for item in references:
    c.writerow(references)

1 Comment

Since references is just a list of strings, the first one still breaks each string up into characters. And the second one writes N identical copies of a row with N columns, instead of N different rows of 1 column.
0
c = csv.writer(open("file.csv", 'w'))
c.writerows(["Reference"])

# cat file.csv
R,e,f,e,r,e,n,c,e

but

c = csv.writer(open("file.csv", 'w'))
c.writerow(["Reference"])


# cat file.csv
Reference

Would work as others have said.

My original answer was flawed due to confusing writerow and writerows.

2 Comments

Why would you do writerows([item]) instead of just writerow(item)? It's the same thing, but more complicated…
My bad. I tested using writerow and got the OPs result with a string but then told them to change it for writerows.

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.