I was playing around with Path
objects and found an interesting behaviour. When testing with python3.11, Path.glob
returns a generator
object.
>>> from pathlib import Path
>>>
>>> cwd = Path.cwd()
>>> cwd.glob("*")
<generator object Path.glob at 0x100b5e680>
>>> import sys;sys.version
'3.11.6 (v3.11.6:8b6ee5ba3b, Oct 2 2023, 11:18:21) [Clang 13.0.0 (clang-1300.0.29.30)]'
I tested the same code with Python3.13, but this time it returns a map
object.
>>> from pathlib import Path
>>>
>>> cwd = Path.cwd()
>>> cwd.glob("*")
<map object at 0x101867940>
>>> import sys;sys.version
'3.13.0 (v3.13.0:60403a5409f, Oct 7 2024, 00:37:40) [Clang 15.0.0 (clang-1500.3.9.4)]'
I know the result can be obtained by wrapping it in a list, but I am curios to understand why this change was made. My initial thought was that it might be because of the performance reasons. But a quick test shows that python3.13 version slower than python3.11 on my system.
Here is the benchmark result:
$ python3.11 -m timeit -n 20000 'from pathlib import Path;cwd=Path.cwd();r=list(cwd.glob("*.py"))'
20000 loops, best of 5: 72.9 usec per loop
$ python3.13 -m timeit -n 20000 'from pathlib import Path;cwd=Path.cwd();r=list(cwd.glob("*.py"))'
20000 loops, best of 5: 75.1 usec per loop
pathlib.Path.glob
learned a bunch of new things in Python 3.13, and I suspect the change in return value type from one generator type to another generator was part of that:
Changed in version 3.13: The recurse_symlinks parameter was added.
Changed in version 3.13: The pattern parameter accepts a path-like object.
Changed in version 3.13: Any OSError exceptions raised from scanning the filesystem are suppressed. In previous versions, such exceptions are suppressed in many cases, but not all.
The particular change that made glob()
return a map
is in this PR (found via git log -S "map(self._from_parsed_string"
) – you can read the description and commit message there for all the details.