Course
Many Python programs need to navigate the file system to read and write files. A common operation is to fetch the current working directory, which is often abbreviated to CWD.
Python has two main modules that can be used to access the filesystem paths: the os module and the pathlib module.
The os module offers the traditional approach to getting the current working directory and works with paths and the filesystem.
The pathlib is a newer module that offers an object-oriented approach that's robust and cross-platform.
In this tutorial, I explore the various techniques to fetch and manipulate the current working directory. If you want to learn more about Python, feel free to explore some of my other blog posts:
- Python Cache: Two Simple Methods
- Python timedelta: Working With Time Intervals in Python
- How to Convert String to Bytes in Python
Python: How to Get the Current Working Directory (CWD)
The current working directory is the directory in which a Python program is executed. It serves as a reference point for relative file paths and allows the program to access files and resources within the directory hierarchy.
Let's look at how to access the current working directory using the os and pathlib modules and compare the two solutions.
Using os.getcwd()
The os module allows access to the computer's operating system. The getcwd() function fetches the current working directory:
import os
cwd = os.getcwd()
print(cwd)
/Users/sg/Documents/GitHub/datacamp
The output shows the path of the directory containing the script. The path's format depends on the operating system. The above output is for POSIX operating systems such as Linux, Unix, and macOS.
The same path on a Windows system would display as follows:
C:\Users\sg\Documents\GitHub\datacamp
The value returned by os.getcwd() is a string:
print(type(cwd))
<class 'str'>
Therefore, we need to use string methods and other string operations to deal with this path.
Using pathlib.Path.cwd()
Python 3.4 introduced the pathlib module, which offers an object-oriented approach to accessing and manipulating file paths. The main class in pathlib is Path, which we can import before getting the current working directory:
from pathlib import Path
cwd = Path.cwd()
print(cwd)
/Users/sg/Documents/GitHub/datacamp
The printed output from Path.cwd() looks similar to the value returned by os.getcwd(). However, Path.cwd() doesn't return a string. We can confirm this by printing the type for the object returned or displaying its official string representation using repr():
print(type(cwd))
print(repr(cwd))
<class 'pathlib.PosixPath'>
PosixPath('/Users/sg/Documents/GitHub/datacamp')
On a Windows computer, Path.cwd() returns a WindowsPath object.
The PosixPath and WindowsPath objects provide similar functionality to enable cross-platform programs. Here are some of these objects' attributes:
print(cwd.parent)
print(cwd.name)
/Users/sg/Documents/GitHub
datacamp
Whenever possible, it's preferable to use the pathlib module, which is more modern and makes dealing with paths easier. You can read this comprehensive guide to using pathlib in Python if you want to learn more.
Working With the Current Directory
Python programs often need to manipulate the path, for example, to save a file in a subfolder. Let's assume we need to create a new subdirectory in our current working directory and save a text file in the new folder.
Using the os module
The getcwd() function in the os module returns a string. Therefore, it's possible to manually alter this string to modify the path. However, the modifications needed vary depending on the operating system since different systems have different path formats. A better option is to use os.path.join():
import os
cwd = os.getcwd()
output_path = os.path.join(cwd, "testing_os")
print(output_path)
/Users/sg/Documents/GitHub/datacamp/testing_os
The path that os.path.join() returns is in the correct format for the operating system being used. This returns a string with the new path. We can check whether this subfolder exists with os.path.exists(), which returns a Boolean:
print(os.path.exists(output_path))
False
This shows that the path represented by output_path doesn't exist yet. The os module provides tools to create this folder. The function os.mkdir() makes a new directory:
os.mkdir(output_path)
print(os.path.exists(output_path))
True
The new subfolder now exists, and new files can be saved in this folder:
output_file = os.path.join(output_path, "test.txt")
with open(output_file, "w") as file:
file.write("Testing path modification with the 'os' module")
The variable output_file contains the name of the desired output file with the full path. This text file is created in the subfolder /testing_os within the current working directory.
We can also list all the items in a folder using os.listdir():
for item in os.listdir(output_path):
print(item)
test.txt
The function os.listdir() returns a list with all the items in the directory. This code iterates through this list to display each file or folder on a separate line. In this example, the directory contains a single text file.
Using the pathlib module
The newer pathlib module also provides tools to create new paths. This module uses the forward slash operator / to combine elements into a path. This is the same operator that's used for the division of numeric data types, but it's also the character used in file paths in POSIX operating systems. Let's create a new path and check that it doesn't already exist:
from pathlib import Path
cwd = Path.cwd()
output_path = cwd / "testing_pathlib"
print(output_path)
print(Path.exists(output_path))
/Users/sg/Documents/GitHub/datacamp/testing_pathlib
False
The Path class has its own .mkdir() method to create a new directory:
Path.mkdir(output_path)
print(Path.exists(output_path))
True
Since output_path is a PosixPath or WindowsPath object, we can use the forward slash operator anywhere to create a new path:
with open(output_path / "test.txt", "w") as file:
file.write("Testing path modification with the 'pathlib' module")
The new text file is created in the /testing_pathlib folder.
We can use the Path method .iterdir() to iterate through each item in a folder:
for item in Path.iterdir(output_path):
print(item)
/Users/sg/Documents/GitHub/datacamp/testing_pathlib/test.txt
As with other tools in pathlib, the value returned is not a string. Instead, it's a PosixPath or WindowsPath object. We can use the .name attribute to display the file or folder name without the full path:
for item in Path.iterdir(output_path):
print(item.name)
test.txt
Whereas os.listdir() returns a list, pathlib.Path.iterdir() returns a generator object (you can read this tutorial on Python Iterators and Generators if you need a refresher):
print(Path.iterdir(cwd))
<generator object Path.iterdir at 0x1036b2c20>
This behavior follows the best practices in modern Python since iterators and generators are more efficient in certain situations.
Changing the Current Working Directory (CWD)
It's also possible to change the current working directory directly from within a Python program using os.chdir(). Since this is not an operation that's directly related to the path, there's no alternative version in pathlib. However, we can still use pathlib.Path objects as arguments:
import os
from pathlib import Path
cwd = Path.cwd()
print(cwd)
os.chdir(cwd.parent)
cwd = Path.cwd()
print(cwd)
/Users/sg/Documents/GitHub/datacamp
/Users/sg/Documents/GitHub
The working directory has now changed. We can also use cwd.parent.resolve() to ensure any symbolic links are dealt with correctly. The argument in os.chdir() can also be a string, such as the paths returned by functions in the os module.
Caution is needed when changing the working directory within a program to ensure there aren't any unexpected behaviors.
Best Practices and Tips
Here are some best practices and tips when working with paths in Python:

Conclusion
Navigating and manipulating file paths is a common requirement in many Python programs. The os module provides the traditional functions for handling these tasks, while the pathlib module offers a more modern, object-oriented approach. Using pathlib not only simplifies many operations but also ensures that your code remains cross-platform and easier to read.
Whether you're maintaining an existing codebase that uses os or starting a new project where you can leverage pathlib, understanding both modules and their capabilities will give you the flexibility and confidence to manage paths in any Python project.
You can carry on your Python learning journey with these courses:
I studied Physics and Mathematics at UG level at the University of Malta. Then, I moved to London and got my PhD in Physics from Imperial College. I worked on novel optical techniques to image the human retina. Now, I focus on writing about Python, communicating about Python, and teaching Python.

