How to Use pathlib in Python
In Python, the pathlib
module allows you to manipulate file and directory (folder) paths as objects.
You can perform various operations, such as extracting file names, obtaining path lists, and creating or deleting files, more easily than with the traditional os.path
module.
This article explains the basic usage of the pathlib
module.
All sample code in this article assumes that the pathlib
module has been imported. No additional installation is required since it is included in the standard library.
import pathlib
It is also common to import only the Path
class. In this case, pathlib.Path()
is used as Path()
.
from pathlib import Path
The following file and directory structure is used as an example.
temp/
├── dir/
│ └── sub_dir/
│ └── file2.txt
└── file.txt
Path
objects
The pathlib.Path()
constructor
The pathlib
module allows you to manipulate paths as objects.
You can create a Path
object using the pathlib.Path()
constructor by specifying a path string. It can be either a relative or an absolute path.
p_file = pathlib.Path('temp/file.txt')
print(p_file)
# temp/file.txt
print(type(p_file))
# <class 'pathlib.PosixPath'>
Omitting the argument yields a relative path representing the current working directory. Equivalent to pathlib.Path('.')
.
print(pathlib.Path())
# .
print(pathlib.Path() == pathlib.Path('.'))
# True
pathlib.Path()
creates an instance of a class according to the execution environment. For example, it creates a PosixPath
instance on Unix-like systems and a WindowsPath
on Windows.
PosixPath
and WindowsPath
are subclasses of Path
.
print(issubclass(pathlib.PosixPath, pathlib.Path))
# True
print(issubclass(pathlib.WindowsPath, pathlib.Path))
# True
In most cases, there is no need to distinguish between PosixPath
and WindowsPath
for use, and in this article, objects of both types are collectively referred to as Path
objects.
Path
and PurePath
Path
is known as a concrete path, with PurePath
as its parent class.
PurePath
provides purely computational operations without filesystem access, while Path
provides I/O operations, such as reading or writing files. Since Path
is a subclass of PurePath
, all methods and attributes of PurePath
are also available in Path
.
print(issubclass(pathlib.Path, pathlib.PurePath))
# True
For example, to handle Windows-style paths on a Unix machine (or vice versa), create PurePosixPath
or PureWindowsPath
instances. However, for actual file and directory processing, pathlib.Path()
should suffice.
Methods and attributes of Path
Various operations can be performed using the methods and attributes of the Path
object.
For example, to determine if the path points to a file, use the is_file()
method, and to get the extension as a string, use the suffix
attribute.
p_file = pathlib.Path('temp/file.txt')
print(p_file.is_file())
# True
print(p_file.suffix)
# .txt
Note that suffix
is an attribute of PurePath
, but since PurePath
is inherited by Path
, it can also be used from instances of Path
.
Thus, the basic flow of using pathlib
is to create a Path
object that points to the desired file or directory and then manipulate it with its methods and attributes.
Handle non-existent paths
It is also possible to create Path
objects for non-existent paths. The exists()
method returns False
for these paths.
p_new_file = pathlib.Path('temp/new_file.txt')
print(p_new_file.exists())
# False
New files or directories can be created from objects of non-existent paths. For example, the touch()
method creates an empty file.
p_new_file.touch()
print(p_new_file.exists())
# True
You can also chain methods in a single line.
pathlib.Path('temp/new_file2.txt').touch()
Using the iterdir()
method to list the contents of a directory allows you to verify the presence of newly created files.
for p in pathlib.Path('temp').iterdir():
print(p)
# temp/file.txt
# temp/new_file.txt
# temp/new_file2.txt
# temp/dir
Navigate paths: /
, joinpath()
, parent
, etc.
You can create Path
objects for different directories or files based on an existing Path
object, similar to navigating a directory tree.
Join paths
Using the /
operator with Path
objects and path strings concatenates paths.
p_dir = pathlib.Path('temp/dir')
p_sub_dir_file = p_dir / 'sub_dir' / 'file2.txt'
print(p_sub_dir_file)
# temp/dir/sub_dir/file2.txt
print(p_sub_dir_file.is_file())
# True
Paths can also be joined using the joinpath()
method, which serves the same purpose as os.path.join()
.
p_sub_dir_file = p_dir.joinpath('sub_dir', 'file2.txt')
print(p_sub_dir_file)
# temp/dir/sub_dir/file2.txt
print(p_sub_dir_file.is_file())
# True
Move to parent directories
Concatenate ..
Concatenating ..
moves to the parent directory.
p_dir = pathlib.Path('temp/dir')
p_file_join = p_dir.joinpath('..', 'file.txt')
print(p_file_join)
# temp/dir/../file.txt
The samefile()
method checks if two paths refer to the same file. Note that the ==
operator returns False
in this case.
p_file = pathlib.Path('temp/file.txt')
print(p_file.samefile(p_file_join))
# True
print(p_file == p_file_join)
# False
To convert a relative path into an absolute path, use the resolve()
method.
print(p_file_join.resolve())
# /Users/mbp/Documents/my-project/python-snippets/notebook/temp/file.txt
print(p_file.resolve())
# /Users/mbp/Documents/my-project/python-snippets/notebook/temp/file.txt
print(p_file_join.resolve() == p_file.resolve())
# True
To convert an absolute path into a relative path, use the relative_to()
method. It returns a relative path to the specified base path.
Utilizing cwd()
method, you can convert an absolute path to a path relative to the current directory as follows.
print(p_file_join.resolve().relative_to(pathlib.Path.cwd()))
# temp/file.txt
The parent
attribute
To move to the parent directory, you can also use the parent
attribute.
p_dir = pathlib.Path('temp/dir')
print(p_dir.parent)
# temp
print(p_dir.parent.joinpath('file.txt'))
# temp/file.txt
However, note that parent
is purely a lexical operation. It does not interpret ..
.
p_file_join = p_dir.joinpath('..', 'file.txt')
print(p_file_join)
# temp/dir/../file.txt
print(p_file_join.parent)
# temp/dir/..
print(p_file_join.parent.parent)
# temp/dir
The with_name()
method
The with_name()
method creates a new Path
object with a different name in the same directory. This is simpler than moving to the parent directory and concatenating a different file name.
p_file = pathlib.Path('temp/file.txt')
print(p_file.with_name('new_file.txt'))
# temp/new_file.txt
Convert Path
objects to strings (str
)
As shown in the examples so far, outputting a Path
object with print()
displays the path as a string, but its type is still Path
(PosixPath
or WindowsPath
), not a string (str
).
p_file = pathlib.Path('temp/file.txt')
print(p_file)
# temp/file.txt
print(type(p_file))
# <class 'pathlib.PosixPath'>
Use str()
to convert a Path
to a string.
s = str(p_file)
print(s)
# temp/file.txt
print(type(s))
# <class 'str'>
Specify Path
objects as arguments to os
module functions
Although os
module functions traditionally require a path string, many functions now accept Path
objects since Python 3.6.
For example, os.path.isfile()
works correctly with both path strings and Path
objects.
import os
print(os.path.isfile('temp/file.txt'))
# True
print(os.path.isfile(pathlib.Path('temp/file.txt')))
# True
Functions that now accept Path
objects are noted in the official documentation.
Changed in version 3.6: Accepts a path-like object. os.path.isfile() — Python 3.12.2 documentation
Note that there is the is_file()
method for Path
objects corresponding to os.path.isfile()
. For most functions of os
, there are corresponding methods in Path
objects, so there is rarely a need to use os
functions directly.
Correspondence between os
module and pathlib
Module
The official documentation includes a list showing which methods of Path
and PurePath
objects correspond to functions in the os
module.
Key correspondences include:
Operation | os and os.path |
pathlib |
---|---|---|
Get current directory | os.getcwd() |
Path.cwd() |
Replace leading ~ with the home directory |
os.path.expanduser() |
Path.expanduser() , Path.home() |
Check path existence | os.path.exists() |
Path.exists() |
Check if a directory | os.path.isdir() |
Path.is_dir() |
Check if a file | os.path.isfile() |
Path.is_file() |
Check if a symbolic link | os.path.islink() |
Path.is_symlink() |
Check if an absolute path | os.path.isabs() |
PurePath.is_absolute() |
Convert to absolute path | os.path.realpath() |
Path.resolve() |
Convert to relative path | os.path.relpath() |
PurePath.relative_to() |
Get status | os.stat() |
Path.stat() , Path.owner() , Path.group() |
Join paths | os.path.join() |
PurePath.joinpath() |
Get base name | os.path.basename() |
PurePath.name |
Get parent directory | os.path.dirname() |
PurePath.parent |
Split and get extension | os.path.splitext() |
PurePath.stem , PurePath.suffix |
Create directory | os.makedirs() |
Path.mkdir() |
Remove directory | os.rmdir() |
Path.rmdir() |
Remove file | os.remove() , os.unlink() |
Path.unlink() |