12  Path and file handling

Input and output (I/O) functionality is an important part of software development. In this section we introduce the pathlib module as a structure and pythonic way to deal with paths. Furthermore, we show some basic file read and write interaction to round off the topic.

The module pathlib allows us to move away from paths as strings and combines all the file and path operations into a single module, where a path is represented by the class Path. Before pathlib these operations where spread over os, glob, and shutil. Furthermore, pathlib provides a cross-platform way to read, write, move, and delete files.

The main object we are going to work with is Path, which is a superclass of PosixPath and WindowsPath and the platform agnostic version of a file system path.

Let us look at an example here first, we always call the same function on different systems:

from pathlib import Path

Path.cwd()
PosixPath('/home/lecturer/lectures/MECH-M-DUAL-1-SWD')
PosixPath('/Users/lecturer/lectures/MECH-M-DUAL-1-SWD')
WindowsPath('C:/Users/lecturer/lectures/MECH-M-DUAL-1-SWD')

As we can see from the different outputs per platform, the module takes care of the differences but allows us a unified experience.

Warning

Of course we can use the specific versions like PosixPath but be aware that this results in a problems when using we are on the wrong platform.

from pathlib import WindowsPath

WindowsPath('test.txt')
---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
Cell In[4], line 3
      1 from pathlib import WindowsPath
----> 3 WindowsPath('test.txt')

File /opt/hostedtoolcache/Python/3.12.12/x64/lib/python3.12/pathlib.py:1434, in WindowsPath.__new__(cls, *args, **kwargs)
   1433 def __new__(cls, *args, **kwargs):
-> 1434     raise NotImplementedError(
   1435         f"cannot instantiate {cls.__name__!r} on your system")

NotImplementedError: cannot instantiate 'WindowsPath' on your system

Of course we can define our path via a string and convert it back to a string.

from pathlib import Path

p = Path()
print(str(p))
/home/lecturer/lectures/MECH-M-DUAL-1-SWD

Again, pathlib will make sure to respect the platform specifics.

If we want to join paths we can use the / operator

intro = p / "intro.qmd"
print(intro)
/home/lecturer/lectures/MECH-M-DUAL-1-SWD/intro.qmd

or joinpath()

intro = p.joinpath("intro.qmd")
print(intro)
/home/lecturer/lectures/MECH-M-DUAL-1-SWD/intro.qmd

As mentioned we can use the same interface for file access so

with intro.open() as f:
    print(f.readline())
# Introduction {.unnumbered}

will allow us to read the first line of the introduction to these notes. We can use the usual functions to read as bytes or with a specific encoding like utf-8.

Important

pathlib provides us with great possibilities to work with the file system in our program. Furthermore, as we can see from the above examples, it allows us to always us relative paths in the code and still have the absolute path on the system.

This greatly helps us to make the code portable to different locations and work on different platforms.

Have a look into the following references to get an idea of the further possibilities and to help you solve the exercises in the appendix.

12.1 References

You can find further information in the following sources:

  • The official documentation, link
  • A nice RealPython introduction to the topic link