 My favorite module I use a lot. Let me just type it out. CSV. I do a lot of B2B stuff. And guess what? I deal a lot with Excel files. And an easy way to deal with Excel files is to dump the CSV and process them with Python. Let's just create, I don't know, a simple CSV file. Let's just, I don't know, maybe all my module a month talks like. So I had one February and June and October and November. Let's print that out. So I have the module a month and the date I gave it, right? Simple table. We've all dealt with this. Let me try splitting that by hand, right? So this is a big string. I want to split that into a list of lists, right? This is a table. So if I split by hand, I create an empty list. And for, let me split that by a return line. And so for each row, I'm going to split by hand by commas, because it's comma separated values, right? So let me run that. And let me import pprints to make it nice to print. Let's try that. And all the dates are cut up. And there's like double quotes. And it's kind of really awkward. And let me try. There's a standard library in Django. Let me try the CSV module, what it does for me. So import CSV. Get myself what they call a reader. So the reader will take any iterable. So it'll take a file, for example. In this case, I'm kind of lazy. I'm going to get a list of strings. But the classic example, you just punt in an open file or sys.standardin. And that will give you an iterator, right? And that iterator is of each row. And so I can get the first row, which is my header. Or I can get all the other rows. So let me pprint the list, spitting out all the lists, all the elements of that iterator. And they come out fine. The dates, the double quotes are stripped. The commas in sign are kept. It's a table of two elements. It's a list of each list itself as two elements. It did exactly what I wanted to do. You can go a bit fancier. I really like the dict reader. So again, taking my iterable of rows. And what the dict reader does is it turns every row into a dictionary, taking the column headers and dumping those in the dictionary of each. So if you want to process a big file and don't want to always remember, all right, this row is an offset five. You just spit out a dict and deal with that dict throughout. And also, go figure if your users give you a CSV file while the columns aren't the same order, it doesn't matter as long as the headers make sense. This will complain bitterly if the number of columns don't match the header and all. It'll be a nice error. You'll know right away where it failed. You'll be right at reading it, not five lines later when you're trying to process it. Writing CSV files. So you want to write something. You want something you can give to an end user they can open in Excel and play with. Well, go figure. Let me just write out some data. Let me give a rating to all my talks. That one was great. That one was OK. This one, let's say meh. And final one, it was bad. And let me give some details on our turn line just to make it a bit fancier, right? Now, this is the writer we'll write to a file. The CSV module is built around processing a long file and dumping out a long file. So a very unix sort of file in, file out. So they all kind of need files. Or in my case, I'm going to fake with a string IO package which creates a file like object, but it's basically just in memory and you can deal with as a string. So let me call my out file. And let me create a writer, add a reader, now I have a writer. I tie it to my out file and I write my rows, data. And from my string IO thing, let me get my value and I get the CSV file with the double quotes. The return line appears, but because it's within double quotes Excel will consider part of the same column. It's all beautiful. You can send that around. Everybody's happy. And finally, you can do the same thing with dictionaries. So go figure, let me try another file. Let me get a header. You got the Dick writer. This time you have to specify the header because you need to specify the order of the columns that you want to spit out in the CSV file. So your header is just this list. And you just dumped. So I'm going to create my dictionary data as a dictionary really quick. Let me print that out, just prove to you I'm not cheating. So this is all the data in Python dictionaries and I can punt that into my writer. And if I print out my writer, I got a beautiful CSV file. I can put it into a file, give to all normals that don't use Python. And that's interoperability in one second left. Any questions? There's plenty more in that module by figuring out like there's tabs. It'll work on tabs that are created files, comma separated files, and there's plenty of stuff in there that'll try to sniff out what type of file you're dealing with to make things easier. All right, any questions?