Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

The itertools, pathlib, and calendar Modules

00:00 In the previous lesson, I showed you how error messages have improved in Python 3.12. In this lesson, I’m going to cover changes to three different standard library modules.

00:10 Python 3.12 sees the addition of a new function to the itertools module called batched(). It takes an iterable and returns a series of groups.

00:21 Say you have a list of things you want to show on a page and want to group it into columns. This is a convenient way of doing just that. Back to the REPL, and let’s check it out.

00:33 Before hitting the 3.12 world, a quick detour. There’s a great third-party library out there called more-itertools, and it has a function that is quite similar to batched().

00:45 It’s called chunked(). Let me create some data. Now I can iterate over the string.

01:01 Strings as iterables return a letter at a time. Instead, if I use chunked(),

01:14 I get a series of lists with four items at a time. The columns in my rows I mentioned before. Let’s see how this has been added to the standard library in Python 3.12.

01:28 Importing … build my string again … and this time, I’ll use batched() instead of chunked().

01:47 The only difference is you get tuples instead of lists. I’ve used chunked() a bunch when laying out cards on a webpage, so in the future, this will mean one less third-party library dependency for me.

02:02 I really like the pathlib module. It feels far more Pythonic than its predecessor. I’m not sure why, but I only discovered it in the last couple years, but evidently it’s been around since Python 3.4.

02:14 If you’re not familiar with it, it covers all of what os.path does along with some of what the os module does, but in a more object-oriented fashion.

02:24 A common activity when dealing with a directory is to loop over its contents. Prior to 3.12, Path did have a way of iterating over a directory, but it didn’t handle subdirectories. To do so, you’d write a recursive function to descend into any subdirectories found, and then calling the iteration method once more.

02:43 This always seemed like a shortcoming, especially seeing as the os module had a .walk() method. Well, so now 3.12 has one as well.

02:53 It does all that subdirectory iteration for you, allowing you to iterate over an entire tree. Off to the REPL once more, this time to take a walk. As I’m going to be walking a directory structure, I needed a directory structure. I’m showing it here using the tree utility.

03:12 It comes with some Unix variations, but not with all, but it’s a good tool. If you don’t have it, it’s worth downloading. As you can see, it descends a directory and prints out a tree version of its contents.

03:24 For the case of this exercise, this is what I’m going to be walking. To take a walk, first I need a path. When you work with pathlib, you create objects based on a file or a directory.

03:39 And that would be the Path object for the musicians/ subdirectory. Let me stick this in a variable so I can do stuff with it. Now I’m going to walk the path. The .walk() method returns a series of tuples.

03:57 Each tuple contains the name of the directory, the list of subdirectories inside of it, and the list of files inside of it. Build that into a for loop …

04:15 print some info …

04:28 and there you can see what .walk() returns. From that tree, I have three directories: the root musicians/ folder, one for trumpet/, and one for vocal/.

04:38 Each row consists of a tuple, and that tuple contains the contents. For example, the musicians tuple has a list of directories, which is the trumpet/ and vocal/ subdirectories, and the single readme file inside of it.

04:52 .walk() then descends into trumpet/ and then descends into vocal/ as well. The default processing order is top-down, but you can do bottom-up as well.

05:03 You control this by adding the top_down argument.

05:12 The default is True, so this will do the exact same thing you saw before. By changing it to false,

05:32 I get the output the other way around. To see a practical example, here’s something I cribbed from the docs.

06:17 This walks the directory, uses the .stat() method on each one of the files in the directory, and then sums up their size totals, and then counts how many non-files there are in the directory itself. Let me hit Enter and this is the output for my dummy musicians/ structure.

06:37 It’s mostly placeholder files, as you can see by the tiny byte totals. The last little addition is to the calendar module. Did you know there was a calendar module?

06:50 It even has a callable feature where you can print a calendar from the command line. I chopped this one at March to fit it on the screen, but all twelve months would normally be there.

07:00 There are two small additions to calendar in 3.12. Both are Enum classes, one for the months of the year and the other for the days of the week.

07:10 Back into the REPL I go. I’m going to import calendar and there’s the new Month enum. If I cast it to a list, you can see it has an entry for each month in the year.

07:31 The other enum is Day. And it has the names of the days of the week. Thor would be proud. All right, let’s do something with this. I’m going to grab a date.

07:53 3.12’s release date is as good as any to play with. And the .weekday() method on the date object returns a number, and this number is kind of the reason for adding the enums.

08:08 Just what does 0 mean? Well, I can create an instance of Day with it and find out.

08:23 0 means Monday. Enums have members that allow you to get at the name, the numeric value, and the Enum instance itself. I’ll demonstrate the difference with a quick sales report.

08:40 These are my sales numbers for twelve months. Now I can iterate over the Month enum …

09:00 and print the object’s value, name, and use it to index the sales loop. Note the -1 there in the third term. I’m converting month 1 to 0 to get the first thing in my list.

09:13 And the results … there you go, one enum-based sales report. I hope those numbers are in millions. It wouldn’t be a Python release without some additions to the typing mechanism.

09:27 Next up, I’ll show you those.

Become a Member to join the conversation.