[New-bugs-announce] [issue34541] pathlib.Path.iterdir doesn't throw an exception until you start iterating

Paul Pinterits report at bugs.python.org
Wed Aug 29 04:20:21 EDT 2018


New submission from Paul Pinterits <rawing7 at gmail.com>:

The fact that `Path.iterdir()` only throws exceptions once you start iterating over it makes it very difficult to write correct code.

Let's look at an example: We'll iterate over all children of a directory and print their file size.

If we try to do it like this, the `try...except` has no effect whatsoever:

try:
    children = path_that_doesnt_exist.iterdir()
except FileNotFoundError:
    print("directory doesn't exist")
for path in children:
    print(path.stat().st_size)

If we explicitly check whether the path exists (and is a directory), we end up with a race condition:

if path_that_doesnt_exist.is_dir():
    print("directory doesn't exist")
else:
    for path in children:
        print(path.stat().st_size)

We can wrap the whole loop in a `try...except`, but then we might end up catching exceptions we didn't intend to catch. (For example, the exception that's thrown when we try to get the size of a broken symlink.)

try:
    for path in path_that_doesnt_exist.iterdir():
        print(path.stat().st_size)  # this can also throw FileNotFoundError
except FileNotFoundError:
    print("directory doesn't exist")

We can manually call `next` on the iterator inside of a `try..except` block, but that's awfully verbose and requires knowledge about iterators and the `next` function:

children = iter(path_that_doesnt_exist.iterdir())
while True:
    try:
        path = next(children)
    except FileNotFoundError:
        print("directory doesn't exist")
        break
    print(path.stat().st_size)

Or we can turn the iterator into a list inside of a `try...except`, which seems to be the best option, but completely defeats the point of having an iterator:

try:
    children = list(path_that_doesnt_exist.iterdir())
except FileNotFoundError:
    print("directory doesn't exist")
else:
    for path in children:
        print(path.stat().st_size)

As you can see, writing correct (and good) code with `iterdir` is more difficult than it has any right to be. Please change this behavior so that exceptions are thrown immediately when `iterdir` is called.

----------
components: Library (Lib)
messages: 324307
nosy: Paul Pinterits
priority: normal
severity: normal
status: open
title: pathlib.Path.iterdir doesn't throw an exception until you start iterating
type: behavior
versions: Python 3.4, Python 3.5, Python 3.6, Python 3.7

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue34541>
_______________________________________


More information about the New-bugs-announce mailing list