A Geek’s Life

Breaking Down a Python One Liner

Recently a friend of mine asked me to help her with a Python script she was working on. The script had to process a log file. So the problem was that the script had to identify the most recently modified log file among the list of log files present in the current working directory. And another issue was that there might be some other files and directories present in the working directory of the script.

So I came up with this one liner to find out the most recently updated log file.

1
sorted([f for f in os.listdir('.') if f.startswith('log')], key=lambda a: os.path.getmtime(a))[-1]

I know it looks scary, and long enough to not fit on a single line, but it shows the expressive nature of Python. That’s one of the reasons I decided to learn it and I ended up liking it!

So lets break it down.

First we need to get the list of all files in the current working directory. The built-in os module in Python provides a utility function listdir which can used as:

1
os.listdir('.')

That returns a list - just another name for an array in Python lingo, containing the names of all files and directories in the current directory of the script. We do need to import the os module for that. So the following must be added at the top in the script:

1
import os

A special thing about log files was that their name starts with log. So now we just need to filter out the log files. Using list comprehension in Python makes it a lot easier.

1
logFiles = [f for f in os.listdir('.') if f.startswith('log')]

This will give us just the list of log files in the current working directory. Sweet.

To find out the most recently modified file, we need to know the last modified time of each file and then sort them according to it. The path sub-module in os module contains a function getmtime that returns the last modified time of the file. It can be used as:

1
os.path.getmtime(filename)

For sorting we need to use the sorted function. Its syntax is:

1
sorted(iterable, key)

The first argument iterable is the list that we want to sort. The second argument key has to be a function which defines the criteria for sorting.

Functions can be defined in two ways in Python. The normal syntax is:

1
2
def addOne(a):
  return a + 1

We can also define an anonymous function known as lambda in Python land. So the above function can be written as a lambda:

1
add = lambda a: a + 1

I use the lambda synatx to define the key for the sorted function.

Our key function would look like this:

1
keyFn = lambda a: os.path.getmtime(a)

This will return the last modified time for the filename represnted by the variable a.

So far, we have this:

1
2
3
logFiles = [f for f in os.listdir('.') if f.startswith('log')]
keyFn = lambda a: os.path.getmtime(a)
logFilesSortedByLastModifiedTime = sorted(logFiles, key=keyFn)

The sorted list that is being returned here is:

1
['least_recently_modified',.....,'most_recently_modified']

We want the last element of the list. In Python, we can use negative indexes with list. So an index of -1 refers to the last element of the list.

Now we have:

1
2
3
4
logFiles = [f for f in os.listdir('.') if f.startswith('log')]
keyFn = lambda a: os.path.getmtime(a)
logFilesSortedByLastModifiedTime = sorted(logFiles, key=keyFn)
mostRecentlyModifiedLogFile = logFilesSortedByLastModifiedTime[-1]

Eliminating the variables, we can write the above four lines in just one line:

1
sorted([f for f in os.listdir('.') if f.startswith('log')], key=lambda a: os.path.getmtime(a))[-1]

Hope that was fun! Happy Coding :)