gh-100562: improve performance of `pathlib.Path.absolute()` (GH-100563)

Increase performance of the `absolute()` method by calling `os.getcwd()` directly, rather than using the `Path.cwd()` class method. This avoids constructing an extra `Path` object (and the parsing/normalization that comes with it).

Decrease performance of the `cwd()` class method by calling the `Path.absolute()` method, rather than using `os.getcwd()` directly. This involves constructing an extra `Path` object. We do this to maintain a longstanding pattern where `os` functions are called from only one place, which allows them to be more readily replaced by users. As `cwd()` is generally called at most once within user programs, it's a good bargain.

```shell
# before
$ ./python -m timeit -s 'from pathlib import Path; p = Path("foo", "bar")' 'p.absolute()'
50000 loops, best of 5: 9.04 usec per loop
# after
$ ./python -m timeit -s 'from pathlib import Path; p = Path("foo", "bar")' 'p.absolute()'
50000 loops, best of 5: 5.02 usec per loop
```

Automerge-Triggered-By: GH:AlexWaygood
This commit is contained in:
Barney Gale 2023-01-05 22:11:50 +00:00 committed by GitHub
parent af5149f30b
commit 7fba99eadb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 10 additions and 5 deletions

View File

@ -748,10 +748,12 @@ class Path(PurePath):
@classmethod
def cwd(cls):
"""Return a new path pointing to the current working directory
(as returned by os.getcwd()).
"""
return cls(os.getcwd())
"""Return a new path pointing to the current working directory."""
# We call 'absolute()' rather than using 'os.getcwd()' directly to
# enable users to replace the implementation of 'absolute()' in a
# subclass and benefit from the new behaviour here. This works because
# os.path.abspath('.') == os.getcwd().
return cls().absolute()
@classmethod
def home(cls):
@ -825,7 +827,7 @@ class Path(PurePath):
"""
if self.is_absolute():
return self
return self._from_parts([self.cwd()] + self._parts)
return self._from_parts([os.getcwd()] + self._parts)
def resolve(self, strict=False):
"""

View File

@ -0,0 +1,3 @@
Improve performance of :meth:`pathlib.Path.absolute` by nearly 2x. This comes
at the cost of a performance regression in :meth:`pathlib.Path.cwd`, which is
generally used less frequently in user code.