FAQ: Learn Python: Files - Writing a CSV File

I am workiing on lesson 9/13 in the LEARN PYTHON: FILES group “Reading Different Types of CSV Files”

Lesson URL is Learn Python 3 | Codecademy

Yep, looks like it’s what I mentioned before. The exercise didn’t ask you to use the newline parameter and that’s why it’s marked as incorrect. The examples provided can sometimes include or exclude code compared to what you need to do in the exercise.

So in the example the variable access_log is a list of dictionaries with the same keys. I was wondering how one would write to a csv if someone had a dictionary where the keys were only said once like this

access_log = {
              "Time" : [time values],
              "Address": [address values],
              "Limit" : [limit values]
}

Since the dictionary is organized in columns and not as a list of rows.

The keys become the first row of the CSV, and the lists could be zipped then iterated to create the subsequent rows and fill in the columns.

"Time", "Address", "Limit"
# iterate over zip object
a, b, c
...

Would it look something like this?

import csv

access_log = {
    "time": [time values]
    "address": [address values]
    "limit": [limit values]
}

fields = access_log.keys()
rows = zip(access_log['time'], access_log['address'], access_log['limit'])

with open('new_csv.csv', 'w') as csv:
    writer = csv.DictWriter(csv, fieldnames=fields)

    writer.writerheader()
    for i in rows:
        writer.writerow(i)

That looks sensible. Give it a try.

I tried it and thought that I would share what I found. It is now acceptable to pass a list/tuple into csv.DictWriter.writerow, it requires a dict object. When I tried to pass the tuple i in it gave me an error like “tuple has no attr ‘keys’” or something of the sort. I’m guessing it uses the .keys attribute to know which column to place it under.

So I had to write a loop that made a new dictionary organized how it is in the example.

Since the zip object is composed of tuples with exactly three values, then unpacking is a simple matter of giving it three variables, a, b, c.

Does anyone know how this is printed?

Did you try opening the file in read mode and list out the contents?

Hi @mtf,

For this example I’d like to print out the new log_writer variable that was written to, not the original logger.csv file.

with open(‘logger.csv’, ‘w’) as logger_csv:
log_writer = csv.DictWriter(logger_csv, fieldnames=fields)
log_writer.writeheader()
for log in access_log:
log_writer.writerow(log)

Printing the log_writer object will consume it, so the best would be to write the file, then read it back in, then iterate that.

A DictWriter object has a '__next__' attribute, if I’m not mistaken. That means we can consume the iterable by printing…

try:
  print (log_reader.next())
except StopIteration:
  print ("Done printing")

This is not tested so let us know how you make out.

Aside

As it turns out, the log_writer object has a 'writerows' attribute so it doesn’t need to be iterated when writing it out.

csv — CSV File Reading and Writing — Python 3.12.0 documentation

This was mentioned in a post by @ionatan some years back, if I recall.

  1. What is the difference between a “field” and a “header” and when when you use both?

  2. In task three of this exercise it ask you to " Create a csv.DictWriter instance called log_writer . Pass logger_csv as the first argument and then fields as a keyword argument to the keyword fieldnames ."

What’s the purpose of adding the “fieldnames=fields” part in the parameter?

  1. In task four of this exercise, it ask you to " Write the header to log_writer using the .writeheader() method."

In a CSV file, what is the header referring to? How does it know what to write for the header?

in this example, the word “field” is variable name which will be used as the “headers.” The “fieldnames” parameter is a sequence of keys that identify the order in which values in the dictionary passed to the writerow() method are written to the file. Or you can think of them as the “column headers” of the rows that will be written to the file.

Consider the following example:

import csv

# "fields" is a variable name which could be named anything: 
fields = ['Column1', 'Column2', 'Column3' ]

with open('file.csv', 'w', newline='') as logger_csv:
    # Create a csv.DictWriter instance called log_writer, and 
    # pass logger_csv as the first argument and then fields as a 
    # keyword argument to the keyword fieldnames . 
    log_writer = csv.DictWriter(logger_csv, fieldnames=fields)
    
    # Now you have to write the "fieldname headers" to file
    log_writer.writeheader()
    
    # A row of data represented as a dictionary
    row = {'Column1': 'Hello', 'Column2':'World', 'Column3':'!'}
    
    # Now write the row to file!
    log_writer.writerow(row)

This will write a csv file like the screenshot below.
image

In this example, Column1, Column2, Column3 are the “headers” which are specified by keyword argument fieldnames in the code above. Does that answer your question? If you have any further questions or comments please ask.

It’s a lot clearer now, thanks for clarifying it.

So do you always have to:

  1. have something similar to this part of the code every time you are writing a CSV file?
    “fields = [‘Column1’, ‘Column2’, ‘Column3’ ]”

  2. what happens if you don’t write “log_writer.writeheader().” I assume it just wont have the “fieldname headers” on the CSV file?

Question: Do you always have to have something similar to this part of the code every time you are writing a CSV file?

This depends if you need headers or not. Alternatively, you can use “csv.writer” and write a csv file:

import csv

with open('example.csv', 'w') as file:

    #  Create a csv writer instance
    writer = csv.writer(file)
    # Write data to file
    data = ["This", "is", "a", "Test"]
    writer.writerow(data)

Which would produce the following file:

image

Of course you could add a header to this file with the following line of code:

writer.writerow(['Column1', 'Column2', 'Column3', 'Column4'])

image

Question: what happens if you don’t write “log_writer.writeheader().

When using “csv.dictwriter” the writeheaders() method is optional. Again, it depends if you want headers or not.

Advantages of CSV Dictwriter

In my opinion, because dictWriter.writerow requires a dictionary it make it more obvious which Column the data is being written to which makes the code more readability.

Hope this helps!

i think the code should be right … but i can’t get through this error-message… any suggestions? thank you very much!
afbeelding

Hi @code0004814682! Welcome to the forums!

It’s not letting you proceed because of the line

fields = ['time', 'address', 'limit']

If you comment it out, you will get the tickmark.

Which is extremely stupid because:

  1. the error message has nothing to do with why your answer is “wrong”.
  2. Your answer is not wrong, given it was used as a demonstration in the lesson example and dedicated a whole paragraph to it. In this particular instance you can skip it because it had created for you earlier.

I would submit a bug ticket, as I have. I think this particular exercise was quite lazy and causes confusion among new learners when your curriculum and exercise doesn’t match up.

This is actually a very good observation and might help people in the future. I missed this line entirely first time going through the exercise. Still, the inconsistency of the exercise and the example really throws you off. Considering it was talked about during the lesson, one would think it’d make sense to have the exercise practise writing header names.

@mtf this method doesn’t seem to work. DictWriter doesn’t have a '__next__' attribute when I tested it out. I would think one of the simpler way to see the CSV written as you say would be to read it back, and cast it to a list?

@victoria-dr I raised this issue in the last exercise and I think it’s highly problematic, considering the lesson itself talks about why using the newline = “” is important especially when using OS that produces \r\n for newline and it’s mentioned in the Python documentation as recommended standard practice to avoid issues. Seems counter intuitive for learners to have the exercise invalidate that piece of the lesson and asking them not to do that. I really think it needs to be addressed to avoid confusion.