Use Path.absolute() when you need an absolute spelling of a relative path while retaining its symbolic-link components. Use Path.resolve() when you need a resolved path. The difference matters when .. follows a symbolic link: removing that component as a string operation can change the location the path names.
from pathlib import Path
path = Path('link/../report.txt')
absolute_spelling = path.absolute()
resolved_location = path.resolve()An absolute path starts from a filesystem anchor; it does not necessarily identify a canonical spelling, prove that a file exists, or remove every ... Choose which of those properties your caller actually needs.
Why collapsing the parent component can change the target
Suppose a directory contains target/child, and a link named link points to that child directory. Traversing link/.. reaches target. Removing link/.. lexically instead would leave the directory containing the link. These locations differ.
The following fixture creates only temporary data and removes it afterward. It requires permission to create symbolic links and was checked on macOS with Python 3.11.6; it is not a Windows link-permission test.
from pathlib import Path
import os
import tempfile
with tempfile.TemporaryDirectory() as temporary:
base = Path(temporary).resolve()
(base / 'target' / 'child').mkdir(parents=True)
(base / 'link').symlink_to(base / 'target' / 'child',
target_is_directory=True)
previous = Path.cwd()
try:
os.chdir(base)
p = Path('link/..')
assert p.absolute() == base / 'link' / '..'
assert p.resolve() == base / 'target'
assert Path(os.path.abspath(p)) == base
print('absolute keeps ..; resolve follows the link')
finally:
os.chdir(previous)The official pathlib documentation explicitly distinguishes absolute() from os.path.abspath(): abspath() removes parent components without resolving symlinks. They should not be interchanged simply because both return an absolute path.
Preserve the right starting point
absolute() uses the process's current working directory for relative input. If your application intends a known project directory as its base, retain that base explicitly. Do not depend on whichever directory a launcher happened to select. A relative path is not automatically relative to the source file containing the code.
Nor does absolute() recover a symbolic-link spelling already lost before the call. For example, the operating system's current working directory can be represented physically rather than with the logical spelling a shell displayed. If a UI must retain exactly what a user entered, keep that input separately from the path used for filesystem operations. Do not reconstruct it by guessing prefixes.
Verify identity separately from spelling
Two different path strings may name the same existing file. If that is the actual question, Path.samefile() checks filesystem identity and can raise an error when the comparison cannot be made. An absolute spelling alone provides no such guarantee. Likewise, resolving a path does not freeze the filesystem: another process can change an entry afterward.
resolve(strict=True) requires the path to exist and raises on a missing path. The default non-strict mode resolves as far as possible and appends the remaining portion; do not read its result as proof that every component exists. Permission failures and other errors still need their own handling. Check the documentation for the runtime you deploy, particularly for platform and version differences.
The practical decision is to name the intended contract first: preserve spelling, find a resolved location, or compare existing identities. None of these operations is a substitute for the others, and a path transformation should not silently change which directory the caller intends.