Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function fails on empty sequence

Tags:

python

I am trying to find the date of the newest file in a directory, based on some Python code I shamelessly found on this site.

def newest_file_in_tree(rootfnewer, extension=".avi"):
    return max(
        (os.path.join(dirname, filename)
        for dirname, dirnames, filenames in os.walk(rootfnewer)
        for filename in filenames
        if filename.endswith(extension)),
        key=lambda fn: os.stat(fn).st_mtime)

This works, but fails on empty directories.

    key=lambda fn: os.stat(fn).st_mtime)
ValueError: max() arg is an empty sequence

I concede that I am a Python beginner, and the last line is way beyond my pay grade.

Can anyone suggest how I can trap the error and prevent the function from crashing?

like image 925
Milliways Avatar asked Dec 31 '25 10:12

Milliways


2 Answers

max has a default keyword:

m = max([], key=lambda x: abs(x), default='empty...')
print(m) # 'empty...'

the default will be returned if the iterable is empty. without the default this would raise a ValueError.


a different way for you to go would be to use glob in order to list the files:

import os
from glob import glob

def newest_file_in_tree(rootdir, ext='.avi'):
    glob_wildcard = os.path.join(rootdir, '**/*{}'.format(ext))
    glob_gen = glob(glob_wildcard, recursive=True)
    return max(glob_gen, key=lambda fn: os.stat(fn).st_mtime, default='?')

or even more concise with pathlib:

from pathlib import Path

def newest_file_in_tree(rootpath, ext='.avi'):
    return max(Path(rootpath).glob('**/*{}'.format(ext)),
               key=lambda pth: pth.stat().st_mtime, default='?')
like image 128
hiro protagonist Avatar answered Jan 02 '26 23:01

hiro protagonist


You can separate out that monstrously pythonic one liner into two separate lines, to make sure that max is called only when you have a non-empty list of files from which you pick the newest one:

def newest_file_in_tree(rootfnewer, extension=".avi"):
    files = [
        os.path.join(dirname, filename)
        for dirname, dirnames, filenames in os.walk(rootfnewer)
        for filename in filenames
        if filename.endswith(extension)
    ]

    if files:
        return max(files, key=lambda fn: os.stat(fn).st_mtime)

    return None

Not as pretty as @hiroprotagonist's solution, but is more readable.

like image 26
cs95 Avatar answered Jan 03 '26 00:01

cs95



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!