The os module and the working directory

os · Essentials · 7 min

Every relative path your program opens is resolved against the working directory, which is a common source of 'file not found' bugs.

The os module is the standard library's thin layer over the operating system. It wraps system calls such as getcwd, mkdir and stat in Python functions, so the same code runs on Linux, macOS and Windows. Functions that only exist on some systems are documented with an "Availability" note, for example os.fork (Unix only).

A few portable facts tell you where you are:

  • os.name is 'posix' on Linux and macOS, 'nt' on Windows.
  • os.sep is the path separator (/ or \), os.linesep the line ending.
  • os.getcwd() returns the current working directory (cwd).

The cwd is process-wide state. Any relative path you pass to open(), os.listdir() and friends is resolved against it, and it is whatever directory the user launched the program from, not the directory your script lives in. os.chdir(path) changes it for the whole process, including every thread.

That is why robust scripts build paths from a known base instead of relying on the cwd: for files shipped next to your code, start from os.path.dirname(os.path.abspath(__file__)), or pathlib.Path(__file__).parent.

Import it with a plain import os. Avoid from os import *: it would shadow the built-in open with the low-level os.open, which behaves completely differently.

Example

import os

print(os.name in ("posix", "nt"))   # True
start = os.getcwd()
print(os.path.isabs(start))          # True

os.mkdir("sub")
os.chdir("sub")                      # changes cwd for the whole process
print(os.path.basename(os.getcwd())) # sub
open("note.txt", "w").close()        # relative: created inside sub/
os.chdir(start)
print(os.path.exists("sub/note.txt"))  # True

Remember

  • os wraps operating-system calls in portable Python functions
  • Relative paths resolve against the current working directory, not the script's folder
  • os.chdir affects the whole process, so prefer absolute paths built from a known base

Watch out for

  • Assuming a data file next to the script can be opened by its bare name; it depends on where the program was started.

Check yourself

  1. A script at /app/tool.py runs open('config.ini') and is started from /home/ann. Which file does it open?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.python.org/3/library/os.html#os.getcwd