New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pathlib.Path.iterdir doesn't raise an exception until you start iterating #78722
Comments
The fact that 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:
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:
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 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:
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 |
As an afterthought, I'd like to suggest an alternative solution: If changing the |
Made changes, pathlib.Path('.').iterdir() now throws a FileNotFoundError if the path is not valid. |
Work-around: call try:
children = list(path_that_doesnt_exist.iterdir())
except FileNotFoundError:
print("directory doesn't exist")
for path in children:
print(path.stat().st_size) I don't think we can change the |
Yeah, the fact that it returns a generator/lazy iterator seems pretty fundamental to
|
I'm going to close this issue per CAM's rationale above. Use |
I don't believe more_itertools.iter_except almost handles this case, but (a) requires the callable to be passed and (b) can't handle |
…t delay. `pathlib.Path.iterdir()` now immediately raises any `OSError` exception from `os.listdir()`, rather than waiting until its result is iterated over.
Upon reflection I agree. I've put a PR up. Do you have a preference on whether it should be backported? |
A comment from @AA-Turner:
|
…y. (#107320) `pathlib.Path.iterdir()` now immediately raises any `OSError` exception from `os.listdir()`, rather than waiting until its result is iterated over.
Thanks for the fix!
This feels like a change in behavior / improvement, so probably not suitable for a backport. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
Linked PRs
pathlib.Path.iterdir()
without delay. #107320The text was updated successfully, but these errors were encountered: