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

miss-islington webhook-mailer at python.org
Thu Jan 5 17:11:56 EST 2023


https://github.com/python/cpython/commit/7fba99eadb3349a6d49d02f13b1fddf44c674393
commit: 7fba99eadb3349a6d49d02f13b1fddf44c674393
branch: main
author: Barney Gale <barney.gale at gmail.com>
committer: miss-islington <31488909+miss-islington at users.noreply.github.com>
date: 2023-01-05T14:11:50-08:00
summary:

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

files:
A Misc/NEWS.d/next/Library/2022-12-28-00-28-43.gh-issue-100562.Hic0Z0.rst
M Lib/pathlib.py

diff --git a/Lib/pathlib.py b/Lib/pathlib.py
index b959e85d1840..a0678f61b632 100644
--- a/Lib/pathlib.py
+++ b/Lib/pathlib.py
@@ -748,10 +748,12 @@ def __exit__(self, t, v, tb):
 
     @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 @@ def absolute(self):
         """
         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):
         """
diff --git a/Misc/NEWS.d/next/Library/2022-12-28-00-28-43.gh-issue-100562.Hic0Z0.rst b/Misc/NEWS.d/next/Library/2022-12-28-00-28-43.gh-issue-100562.Hic0Z0.rst
new file mode 100644
index 000000000000..56a426589719
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-12-28-00-28-43.gh-issue-100562.Hic0Z0.rst
@@ -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.



More information about the Python-checkins mailing list