How to Use pathlib in Python

Posted: | Tags: Python, File

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

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()

Related Categories

Related Articles