How does `.writeheader()` know the fields to use?

Just want to clarify a few things on this one…?

From the model code explanation:

Now that we’ve instantiated our CSV file writer, we can start adding lines to the file itself! First we want the headers, so we call .writeheader() on the writer object.

This writes all the fields passed to fieldnames as the first row in our file.

^^ Q: This is done without passing any arguments in ‘.writeheader()’?

Then we iterate through our big_list of data. Each item in big_list is a dictionary with each field in fields as the keys. We call output_writer.writerow() with the item dictionaries which writes each line to the CSV file.

^^Q: .writerow() automatically knows that these will be dictionary values and pulles the value data for each key in the list? access_log comes preformatted as a list with dictionary elements, most CSV data won’t come in this format, no?

import csv 

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

TIA!

2 Likes

The argument is passed when the DictWriter() object is instantiated: look at the arguments for DictWriter():

 output_writer = csv.DictWriter(output_csv, fieldnames=fields)

writeheader() is a method of the class DictWriter, and it (writeheader) looks for the list of fields in the fieldnames parameter passed to DictWriter().

Yes, precisely. If you do not have a dictionary to start with, use a different tool (possibly csv.writer).

That is what DictWriter does. It works with data formatted in dictionary form. From the docs, the action of DictWriter is to

Create an object which operates like a regular writer but maps dictionaries onto output rows.

23 Likes

We want to add the columns’ headers to the instance of csv.Dictwriter. In the code below, why should we launch “output_writer.writeheader()”, if earlier we already “showed”, that we want to add the headers: “output_writer = csv.DictWriter(output_csv, fieldnames=fields”?

with open('output.csv', 'w') as output_csv:
  fields = ['name', 'userid', 'is_admin']
  output_writer = csv.DictWriter(output_csv, fieldnames=fields)

  output_writer.writeheader()
  for item in big_list:
    output_writer.writerow(item)

Lesson’ link: https://www.codecademy.com/courses/learn-python-3/lessons/learn-python-files/exercises/writing-a-csv-file

1 Like

It allows for the possibility that you might not want to print the fieldnames as part of your output file,

8 Likes

Thank you. But if I use this expression inside ‘with’ (while the file is opened to changes), I can’t imagine with what another purpose but ‘write’ I can use it.

It would be much easier if it took 3 parameters(output_file, headers, rows).

2 Likes

Can you not imagine that you might want to write to a “data only” .csv file having no headers?

2 Likes

Just in case anyone has the same problem I had:

I didn’t see that the list “fields” had already been established at the top and I made my own. For some reason that made it so that I always failed the last step, even though I did everything right (I even opened the logger csv in read only mode and printed it to check that I had written to the file correctly and it was still failing me). I had to delete my “fields” list in order to pass.

20 Likes

I’m guessing that because fields = [‘time’, ‘address’, ‘limit’] already exists within the code, the algorithm for this step expects the output fields to be in the order: ‘time’, ‘address’, ‘limit’.

Mimicking the example and listing the fields within the ‘open’ block in the same order that they appear in as keys within the dictionaries causes a fail.

2 Likes

How do we know when to use .DictWriter() vs .write() I was going through the hacking project where I had to write into a CSV file and I thought we had to use .DictWriter() instead of just using .write().

I was under the assumption that CSV files needed .DictWriter() while regular txt files used .write()

3 Likes

Aaaaaaah, exactly the answer I was looking for! Thank you. :slight_smile:

Sometimes a little bit weird: One exercise before they explain to you how to use DictWriter and how to create the fieldnames that writeheader() will use and one exercise later they just already added the fields without explaining and as somebody trying to learn this I’m just like: “Wait a moment, we didn’t have to create fieldnames this time, will it work without it, why is this, can it detect the fieldnames from the dictionary keys I’m so confused let’s hide the fields variable in the wall of text above” :rofl:

5 Likes

Patrick, thank you four your explanation. But I’m still having a hard time to understand why should I use log_writer.writeheader().

If I don’t need to pass any arguments into log_writer.writeheader(), why the line output_writer = csv.DictWriter(output_csv, fieldnames=fields) isn’t enough for Python to understand that the readers will be the names found in fields? Ins’t it exactly what is it doing? Informing Python what are the readers of my new .csv file?

1 Like

The point is that, much as the variable pointing to the potential headers (as fieldnames=fields) is stored in the csv.DictWriter() object, you may not want to call the method writeheader.

1 Like

One moment that i discovered is that “write()” method in “w” or “a” mode will only work with strings. And only one string at a time. So e.g. for “fields” list you would have to do “for loop”.
While “DictReader” and “DictWriter” could work with lists of strings.
And of course you don’t need to import “csv” module.

1 Like

if anyone could explain step by step working of these methods (DictReader, DictWriter, writeheader, ) then it will be easily understandable. I am still finding it hard how these commands work.
please explain step by step, how data is being processed.

Your best bet is viewing the documentation for the csv module which describes how these objects are set up-


csv.DictReader
csv.DictWrtier.writeheader

If you really wanted to understand them step by step (which seems unnecessary) you’d need to view the source code which is linked at the top of the csv module documentation.

that escalated quickly to be honest jajaj

The fieldnames argument isn’t there just to provide the text you would use to add header labels to the csv output. It is a required parameter that dictates the order that the fields appear in the file. For example,

log_writer = csv.DictWriter(logger_csv, ['limit', 'address', 'time'])
log_writer.writeheader()

will result in output that looks like this from the example:

limit,address,time
844404,1.227.124.181,08:39:37
543871,198.51.139.193,13:13:35
3021,172.1.254.208,19:40:45

switching the fieldname order like so:

log_writer = csv.DictWriter(logger_csv, ['limit', 'time', 'address'])

Results in this output:

844404,08:39:37,1.227.124.181
543871,13:13:35,198.51.139.193
3021,19:40:45,172.1.254.208

In either case, if you want column headers in the csv output file, use log_writer.writeheader() before or after the iteration loop. If you use it after the loop, the header labels will be in the last row of the file instead of the first.

8 Likes

Thank you! This was useful, I also didn’t notice the ‘fields’ list from above.

Just a little question.
If writeheader is a method of the class DictWriter, why we don’t use the line:

DictWriter.writeheader()

instead?

It’s a function bound to csv.DictWriter designed to work with instances of that class (a method when accessed from instances); at least in the current version of Python it accepts only one parameter self which should be an instance of the csv.DictWriter type. In short, you cannot easily use it on its own.

If your only goal was writing the header then you could probably skip the csv module and just write using the file object itself (using whatever you felt like). But if you’re writing out data to .csv file and your data is stored in dictionaries then the DictWriter type saves us a lot of work.

3 Likes