Paths#

When you open a file on your computer you may use the Finder or File Explorer to click through to each folder and eventually find the file you want. When we want to do the same thing through code we use file paths.

A path is a way to represent the location of a file or folder using text. You can think of it like an address; where a street address points to a physical location in the real world, a path points to a location on a computer.

Paths are used in pretty much all programming languages as well as on the command line, which we’ll be learning about today.

Table of Contents

Part 1. Exploring files on the command line#

For this lesson, open a terminal. We’ll use the ls command which lists files to experiment with different paths. (On Windows you may need to use dir instead.) With no arguments it lists the files in the working directory which is the directory (or folder) that you are currently in.

Listing 228 command line#
$ ls
README.md  contacts.py  hello.txt    pyproject.toml  tests  tools
bin        docs         poetry.lock  pythonclass     tmp    vendor

The ls command takes paths as arguments. When passed, it will list only the matching files.

Tip

Commands on the command line can take arguments but there are some differences from Python. Arguments are separated by spaces, no parenthesis or commas. Single or double quotes are only required if the argument contains special characters, like a filename with spaces.

The simplest path is just a filename.

Listing 229 command line#
$ ls README.md
README.md

Part 1.1: Directory separators#

Directories are separated with a slash (/) or backslash (\) on Windows. For example here’s how I would list the template.py file inside the pythonclass directory.

Listing 230 command line#
$ ls pythonclass/template.py
pythonclass/template.py

On Windows the directory separator is a backslash (\). A slash (/) might work too, depending on which version of Windows and terminal you’re using. Otherwise the same command would be:

Listing 231 command line#
> ls pythonclass\template.py
pythonclass\template.py

Part 1.2: The working directory#

So far all of these examples have been relative meaning that they start from the working directory.

You can explicitly specify the working directory with a ..

Listing 232 command line#
$ ls ./pythonclass/template.py
./pythonclass/template.py

Part 1.3: Parent directory#

You can use .. to indicate the parent directory. For example, I have an arduino directory in the same directory as my working directory python-class. Here’s how I would list its contents.

Listing 233 command line#
$ ls ../arduino
config  docs  examples  sketchbook  tools

Part 1.4: Absolute paths#

When a path starts with a / or the drive (like C:) it is an absolute path. That means that it starts at the computers root directory and contains all of the information to get from there to the file.

Sometimes it’s easier not to start in the working directory, but instead use the complete file location. This is called the absolute path and starts from the root directory, or top-most directory in the file system, indicated by a single /.

So start absolute paths with a slash (/).

Listing 234 command line#
$ ls /etc/group
/etc/group

On Windows you may need to start with the drive letter.

Listing 235 command line#
> ls C:\Windows\system32
C:\Windows\system32

Part 1.5: The home directory#

Operating systems designed to support multiple users usually keep each users files in their own directory not accessible to other users. This is called the home directory and on most operating systems the tilde (~) is a shortcut to the home directory for the current user.

Listing 236 command line#
$ ls ~/Documents
Adobe Autodesk

Part 1.6: Exercise#

Exercise 67 (command-line-paths)

On a Unix-like operating system what is the path for each of the following?

  1. A file named blueberry-muffins.md in a folder named Recipes` in the working directory?

  2. An absolute path to the Music directory of the guest user located under the Users directory.

  3. A file named letter.doc in the parent directory of the working directory.

  4. The Pictures directory in the home directory of the current user.

Part 2: Paths in Python#

Part 2.1: Path strings in open()#

The first argument to the open() function in Python is the path to a file. So far we’ve been using a simple filename. In the following example, a file named contacts.txt in the working directory is opened.

Listing 237 python example#
fh = open("contacts.txt")
contents = fh.read()
fh.close()
print(contents)

But what if you want to open a file somewhere other than the working directory? In that case, you can include the path in the argument. In the following example the contacts.txt file is in a data directory in the working directory.

Listing 238 python example#
fh = open("data/contacts.txt")
contents = fh.read()
fh.close()
print(contents)

Part 2.2: Path objects#

Python provides a pathlib.Path object which makes it easier to construct and manipulate cross-platform paths, provides handy methods for filesystem operations, and can be used in many of the places that string paths are used.

First import the Path class from the pathlib module. Then call Path with a string path argument. For example, here’s how you create a Path object for the README.md file.

Listing 239 python example#
from pathlib import Path

path = Path("README.md")

Part 2.3: Using Path objects in open()#

You can use a Path object instead of a string for the first argument of the open() function.

Listing 240 python example#
from pathlib import Path

path = Path("README.md")
fh = open(path)
contents = fh.read()
fh.close()
print(contents)

Part 2.4: Validation methods#

Path objects provide some handy boolean methods for checking the status of a file or directory.

  • path.exists()

  • path.is_file()

  • path.is_dir()

The following example checks to be sure that the README.md file exists and that it is a normal file before trying to read it.

Listing 241 python example#
from pathlib import Path

def main():
  path = Path("README.md")
  if not path.exists():
    print("Sorry, no file named README.md")
    return

  if not path.is_file():
    print("Unable to read file: README.md")
    return

  fh = open(path)
  contents = fh.read()
  fh.close()
  print(contents)

Part 2.5: Exercise#

Exercise 68 (Validating paths)

Write a function to print the contents of the contacts.txt file. Before reading it, check to make sure the file exists. If it does not, tell the user the file does not exist and return.

Part 2.6: Canonical path#

Path objects provide methods for handling absolute versus relative paths as well as converting symbols for the current operating system.

You can use the .is_absolute() method to check if a path is an absolute or relative.

Listing 242 Python Shell#
>>> path = Path("file.txt")
PosixPath("file.txt")

>>> path.is_absolute()
False

You can use the .absolute() method to return an absolute version of a path object.

Listing 243 Python Shell#
>>> path.absolute()
PosixPath("/home/pythonclass/Documents/file.txt")

Note though, .absolute() does not change the value of path. It is still relative.

Listing 244 Python Shell#
>>> path
PosixPath("file.txt")

To make path absolute, you’ll need to assign it to the path variable using the = operator.

Listing 245 Python Shell#
>>> path = path.absolute()
>>> path
PosixPath("/home/pythonclass/Documents/file.txt")

Finally, you can get the normalized path using the .resolve() method. This will convert shortcuts like .. or ~ to the path and resolve, or follow, any symbolic links (like shortcuts).

Listing 246 Python Shell#
>>> path = Path("../file.txt")
>>> path
PosixPath("../file.txt")

>>> path.resolve()
PosixPath("/home/pythonclass/file.txt")

Part 2.7: Parts of a path#

Python Path objects make it easy to access parts of a path without having to worry about which operating system is being used.

Property

Type

Description

parent

Path

Parent directory.

parts

tuple

Sequence of directories and filename if any.

parents

tuple

Sequence of parent directories.

name

str

Filename.

stem

str

Filename without extension.

suffix

str

Filename extension including .

The following example prints the filename minus the extension using the stem property above the file contents.

Listing 247 python example#
from pathlib import Path

def main():
  path = Path("README.md")

  with open(path) as fh:
    contents = fh.read()

  print(f"*** {path.stem} ***\n")
  print(contents)

Part 2.8: Constructing paths#

One way to construct paths in a way that will work on all operating systems is to use the joinpath() method to add a subdirectory or filename to an existing path.

In the following example the file ~/Documents/groceries.txt is printed to the screen.

Listing 248 python example#
from pathlib import Path

def main():
  home = Path.home()
  basedir = home.joinpath("Documents")
  path = basedir.joinpath("groceries.txt")

  with open(path) as fh:
    contents = fh.read()

  print(f"*** {path.stem} ***\n")
  print(contents)

You can also chain the method calls together like this:

Listing 249 python example#
from pathlib import Path

def main():
  path = Path.home().joinpath("Documents").joinpath("groceries.txt")

  with open(path) as fh:
    contents = fh.read()

  print(f"*** {path.stem} ***\n")
  print(contents)

Finally, you can use the / operator on Path objects as a shorthand for the joinpath() method.

Listing 250 python example#
from pathlib import Path

def main():
  path = Path.home() / "Documents" / "groceries.txt"

  with open(path) as fh:
    contents = fh.read()

  print(f"*** {path.stem} ***\n")
  print(contents)

Part 2.9: Paths relative to current file#

The working directory in Python is the directory the current program was launched from. This can make using relative paths problematic because if the user runs the program from a different directory, the location of any relative paths will change.

Instead you may want to make a path relative to the file that is being run.

Python provides a special variable __file__ that contains a string with the path of the current file. When used to create a Path object, you can use the parent property to get the directory the file is in.

The following example opens the file .vscode/launch.json in the same directory as the current file.

Listing 251 python example#
from pathlib import Path

def main():
  basedir = Path(__file__).parent / ".vscode" / "launch.json"

  with open(path) as fh:
    contents = fh.read()

  print(contents)

Part 2.10: Exercise#

Exercise 69 (Constructing paths)

Write a function to print the contents of a different Python script in your project.

Reference#

Special directories#

Directory

CLI

Python

home

~

Path.home()

working

.

Path.cwd()

parent

..

path.parent

Path examples#

Example

Description

groceries.txt

a file in the working directory

./groceries.txt

same as above

Documents/groceries.txt

a file in the Documents folder in the working directory

/Users/pythonclass/Documents/

MacOS path to the pythonclass user’s Documents folder

/home/pythonclass/Documents/

Unix path to the pythonclass user’s Documents folder

C:\Documents\

Windows path to the pythonclass user’s Documents folder

Glossary#

Paths#

absolute path#

A complete path starting from the root directory.

directory separator#

The symbol used to separate directories in a path, either a slash / or a backslash (\) on Windows.

home directory#

On operating systems that support multiple users, the directory created for and with access restricted to a given user which is intended to contain all of the users files.

On the command line in most systems the shorthand is the tilde character (~). It is usually stored in the environment variable $HOME or on Windows %USERPROFILE% or %HOMEDRIVE%%HOMEPATH%.

path#

A text representation of a file location.

relative path#

A path starting from the working directory.

root directory#

The top-most directory in the file system.

working directory#
current working directory#
CWD#

On the command line, the current directory. In a Python script or shell, the directory that the shell or script was started from.

See also#