pathlib.PurePath

Everything that is pure string logic — parsing, joining, name and suffix, parents, matching — lives on PurePath. It never reads the disk, so it is safe for paths from another machine and for paths that do not exist.

pathlib classPython 3.4+Live demo
Common call
PurePosixPath('/srv/app') / 'config.toml'
Returns
PurePosixPath('/srv/app/config.toml')
Replaces
os.path.join / basename / dirname / splitext on strings
Watch out
PurePath(...) is PureWindowsPath on Windows — pick the flavour explicitly when it matters
pathlib.PurePath(*pathsegments)
→ PurePosixPath | PureWindowsPath

Demo

Live evaluation
See how a string is normalised: repeated slashes and "." vanish, a trailing slash is dropped, ".." stays.
Try:
Inputs
textstrany path text
Code
from pathlib import PurePosixPath
p = PurePosixPath('docs//guide/./intro.md/')
(p, p.parts)
Result
(PurePosixPath('docs/guide/intro.md'), ('docs', 'guide', 'intro.md'))

Normalisation is purely textual, so it only does what is safe without asking the OS: "//" becomes "/", "." segments and a trailing slash go away, but "a/../b" is not "b" (a could be a symlink). Exactly two leading slashes are kept because POSIX lets systems give "//" a special meaning; three or more collapse to one. The empty string means the current directory and prints as ".".

Parameters

NameTypeRequiredDescription
*pathsegmentsstr | os.PathLikeno ('.')Segments joined like os.path.join: an absolute segment restarts the path. No segments means the current directory, shown as ".".

Return value

PurePosixPath | PureWindowsPath — PurePath itself is never instantiated: it returns the flavour of the running OS.

Common patterns

Pick the flavour explicitly
Handle paths from another OS the same way on every machine.
from pathlib import PurePosixPath, PureWindowsPath
remote = PurePosixPath('/var/log/app.log')
share = PureWindowsPath(r'\\fileserver\reports\q3.xlsx')
Type hints that accept strings and paths
Take str or any PathLike, convert once at the edge.
import os
from pathlib import Path
def load(path: str | os.PathLike) -> str:
    return Path(path).read_text(encoding='utf-8')
Use paths as dict keys and in sets
Pure paths are hashable; equal paths hash equal.
from pathlib import PurePosixPath
seen = {PurePosixPath('a/b'), PurePosixPath('a//b/')}
len(seen)  # 1

Examples

1. PurePath picks the OS flavour
import os from pathlib import PurePath, PurePosixPath, PureWindowsPath type(PurePath('x')) is (PureWindowsPath if os.name == 'nt' else PurePosixPath)
Returns
True
2. Normalised on construction
from pathlib import PurePosixPath PurePosixPath('a//b/./c/')
Returns
PurePosixPath('a/b/c')
3. No arguments = current directory
from pathlib import PurePosixPath PurePosixPath()
Returns
PurePosixPath('.')
4. Segments join like os.path.join
from pathlib import PurePosixPath PurePosixPath('/usr', 'local', 'bin')
Returns
PurePosixPath('/usr/local/bin')
5. Sorting compares part by part
from pathlib import PurePosixPath sorted([PurePosixPath('b'), PurePosixPath('a/z'), PurePosixPath('a')])
Returns
[PurePosixPath('a'), PurePosixPath('a/z'), PurePosixPath('b')]
6. The parser attribute (3.13)
from pathlib import PurePosixPath, PureWindowsPath (PurePosixPath.parser.__name__, PureWindowsPath.parser.__name__)
Returns
('posixpath', 'ntpath')
7. Backslash is an ordinary character on POSIX
from pathlib import PurePosixPath PurePosixPath('a\\b').parts
Returns
('a\\b',)
8. Only str and PathLike are accepted
from pathlib import PurePosixPath PurePosixPath(None)
Returns
TypeError: argument should be a str or an os.PathLike object where __fspath__ returns a str, not 'NoneType'

Pitfalls

1. Comparing paths of different flavours
A PurePosixPath never equals a PureWindowsPath, even for the same text, and ordering them raises TypeError.
mixed flavours
from pathlib import PurePosixPath, PureWindowsPath
PurePosixPath('a') < PureWindowsPath('a')
TypeError: '<' not supported between instances of 'PurePosixPath' and 'PureWindowsPath'
same flavour
from pathlib import PurePosixPath
PurePosixPath('a') < PurePosixPath('b')
True
2. Assuming equality means "same file"
Equality is textual after normalisation. "a/../b" and "b" differ; different spellings of one file are only equal after resolve() — or use Path.samefile().
== on text
from pathlib import PurePosixPath
PurePosixPath('a/../b') == PurePosixPath('b')
False
samefile()
from pathlib import Path
Path('a').mkdir()
Path('b').touch()
Path('a/../b').samefile('b')
True

When to use

Use it
  • Path arithmetic on paths that may not exist, or belong to another machine
  • Code that must behave identically on Windows and Linux (choose PurePosixPath or PureWindowsPath)
  • Tests: no file system needed
Reach for something else
  • Anything that touches the disk (exists, read_text, glob) → Path
  • Resolving ".." or symlinks → Path.resolve()

Notes

CPython impl
Lib/pathlib/_local.py: PurePath.__new__ returns PureWindowsPath if os.name == "nt" else PurePosixPath; parsing happens lazily on first access to drive / root / parts
parser
Added in 3.13: the os.path implementation used for low-level parsing — posixpath for PurePosixPath, ntpath for PureWindowsPath
Flavours
PurePosixPath: "/" only, case-sensitive. PureWindowsPath: "\" and "/", drives and UNC shares, case-insensitive comparison
Hashing
Hashable and immutable; equal paths have equal hashes

FAQ

PurePath only manipulates the path text: joining, splitting, name, suffix, matching. Path is a subclass that adds I/O: exists, read_text, mkdir, glob and so on. Every Path is also a PurePath.