Skip to main content

How to Resolve Python "FileNotFoundError: [Errno 2] No such file or directory"

The FileNotFoundError: [Errno 2] No such file or directory is one of the most common exceptions encountered by Python developers when working with files. It signifies that Python attempted to access a file using a specified path, but no file or directory was found at that exact location.

This guide explains the common causes of this error and provides step-by-step solutions to correctly locate and open your files.

Understanding the Error: The File Path Problem

When you use functions like open(), Python interprets the filename you provide as a path. This path tells Python where to look for the file. The FileNotFoundError simply means Python followed the path instructions but didn't find anything at the specified destination.

Common Causes

  • File Doesn't Exist: The file truly isn't present on the filesystem.
  • Incorrect Path: The path provided leads to the wrong location.
    • Wrong Relative Path: The file isn't located correctly relative to where the script is being run.
    • Wrong Absolute Path: The full path from the root directory is incorrect.
  • Spelling Mistakes: Typos in the filename or directory names within the path.
  • Missing File Extension: Forgetting to include .txt, .csv, .json, etc., in the filename (Windows often hides extensions by default, making this easy to miss).
  • Case Sensitivity: On case-sensitive systems (Linux, macOS), myfile.txt is different from MyFile.txt.
  • Permissions: The script might lack the necessary operating system permissions to access the file's location.

Understanding Path Types: Relative vs. Absolute

Relative Paths

A relative path specifies the file's location in relation to the current working directory (CWD). The CWD is typically the directory from where you executed the Python script.

  • 'my_data.csv': Looks for the file in the CWD.
  • 'data/my_data.csv': Looks for a folder named data within the CWD, and then for my_data.csv inside that folder.
  • '../backup/my_data.csv': Goes up one directory level from the CWD, then looks for a backup folder, and then for the file inside it.

Absolute Paths

An absolute path specifies the file's complete location starting from the root directory of the filesystem. They are unambiguous, regardless of the CWD.

  • Windows: C:\Users\Alice\Documents\project\my_data.csv
  • macOS/Linux: /Users/alice/Documents/project/my_data.csv or /home/bob/data/my_data.csv

Finding Your Current Working Directory (os.getcwd)

If you're unsure what the CWD is when using relative paths, you can easily find it:

import os

cwd = os.getcwd()
print(f"The current working directory is: {cwd}")

# Example Output (Linux/macOS): /home/user/my_python_project
# Example Output (Windows): C:\Users\User\Documents\MyPythonProject

Knowing the CWD helps you construct the correct relative path.

Solution 1: Using Correct Relative Paths

Placing the File in the Same Directory

The simplest case: If you use just the filename (e.g., 'config.txt'), make sure config.txt is located in the exact same folder as the Python script you are running.

Accessing Files in Subdirectories

If the file is inside a folder relative to your script, include the folder name in the path.

# Assumes:
# my_project/
# |- main.py
# |- input_data/
# |- data.csv

# Correct relative path from main.py
file_path = 'input_data/data.csv'
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
print(f"Successfully read {file_path}")
except FileNotFoundError:
print(f"Error: Could not find file at relative path '{file_path}'")

Accessing Files in Parent Directories (../)

Use ../ to navigate up one directory level. Use ../../ to go up two levels, etc.

# Assumes:
# project_root/
# |- config.txt
# |- src/
# |- main.py

# Correct relative path from main.py to config.txt
file_path = '../config.txt'
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
print(f"Successfully read {file_path}")
except FileNotFoundError:
print(f"Error: Could not find file at relative path '{file_path}'")

Best Practice: Using os.path.join

To construct paths in a way that works correctly across different operating systems (handling / vs \ automatically), use os.path.join().

import os

# Assumes script is in 'my_project/src/'
# Wants to access 'my_project/data/results.json'

script_dir = os.path.dirname(__file__) # Gets directory of the current script
project_root = os.path.abspath(os.path.join(script_dir, '..')) # Go up one level
file_path = os.path.join(project_root, 'data', 'results.json')

print(f"Constructed path: {file_path}")

try:
with open(file_path, 'r', encoding='utf-8') as f:
print(f"Successfully opened {file_path}")
# ... read file ...
except FileNotFoundError:
print(f"Error: File not found at constructed path '{file_path}'")

Solution 2: Using Absolute Paths

Using the full, unambiguous path avoids issues related to the CWD.

Finding the Absolute Path

  • File Explorer/Finder: Right-click the file, select "Properties" (Windows) or "Get Info" (macOS). Look for the "Location" or "Where" field. Remember to append the actual filename and extension to the directory path shown.
  • Terminal/Command Prompt: Navigate to the file's directory using cd and then use pwd (Linux/macOS) or cd (Windows, shows current path) to see the full path. Again, append the filename.

Handling Windows Paths (Backslashes and Raw Strings)

Windows paths use backslashes (\), which are escape characters in Python strings. You have three options:

  1. Use Raw Strings (r''): Prefix the string literal with r. This tells Python to treat backslashes literally. (Recommended)
    windows_path = r'C:\Users\User\Documents\data.txt'
    with open(windows_path, 'r', encoding='utf-8') as f:
    print(f.read())
  2. Escape Backslashes (\\): Use two backslashes wherever you need one literal backslash.
    windows_path = 'C:\\Users\\User\\Documents\\data.txt'
    with open(windows_path, 'r', encoding='utf-8') as f:
    print(f.read())
  3. Use Forward Slashes (/): Python on Windows often correctly interprets forward slashes in paths.
    windows_path = 'C:/Users/User/Documents/data.txt'
    with open(windows_path, 'r', encoding='utf-8') as f:
    print(f.read())

Solution 3: Checking File Existence (os.path.exists)

Before attempting to open a file, you can check if it exists at the specified path.

Checking Before Opening

import os

file_path = 'maybe_existing_file.log'

if os.path.exists(file_path):
print(f"File '{file_path}' exists. Opening...")
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
print("File read successfully.")
# Process content
except Exception as e:
print(f"Error reading existing file: {e}")
else:
print(f"File '{file_path}' does NOT exist.")
# Handle the non-existence case

Creating the File if it Doesn't Exist

You can combine the check with file creation using write mode ('w').

import os

file_path = 'new_or_existing.txt'

if not os.path.exists(file_path):
print(f"File '{file_path}' doesn't exist. Creating...")
try:
# 'w' mode creates the file if it doesn't exist, overwrites if it does
with open(file_path, 'w', encoding='utf-8') as f:
f.write("Created new file.\n")
print("File created.")
except Exception as e:
print(f"Error creating file: {e}")
else:
print(f"File '{file_path}' already exists. Appending...")
try:
# Use 'a' mode to append without overwriting
with open(file_path, 'a', encoding='utf-8') as f:
f.write("Appending line.\n")
print("Appended to file.")
except Exception as e:
print(f"Error appending to file: {e}")
note

The check-then-open pattern can have race conditions in concurrent environments, but is often sufficient for simple scripts. Using try...except FileNotFoundError around the open call is another robust way to handle non-existence.

Solution 4: Changing the Working Directory (os.chdir - Use Cautiously)

You can change Python's CWD to the directory containing the file. This allows you to use just the filename in open(). However, this is generally discouraged as changing the CWD can have unintended side effects on other parts of your code that rely on relative paths from the original CWD. Using absolute paths or correct relative paths (with os.path.join) is usually safer.

import os

file_dir = '/path/to/your/data/directory' # Use the actual absolute path
filename = 'data_in_dir.csv'
original_cwd = os.getcwd() # Optional: store original CWD

try:
print(f"Changing CWD to: {file_dir}")
os.chdir(file_dir) # Change CWD

# Now open using just the filename
with open(filename, 'r', encoding='utf-8') as f:
print(f"Successfully opened '{filename}' after chdir.")
# ... read file ...

except FileNotFoundError:
print(f"Error: '{filename}' not found even after changing directory.")
except Exception as e:
print(f"An error occurred: {e}")
finally:
# Optional: Change back to the original CWD
os.chdir(original_cwd)
print(f"Changed CWD back to: {os.getcwd()}")

Other Common Pitfalls

  • Typos: Double-check every character in the path and filename.
  • Missing Extension: Ensure you've included .txt, .log, .csv, etc. If Windows is hiding extensions, change your folder view options to show them.
  • Case Sensitivity (Linux/macOS): MyFile.txt and myfile.txt are different files. Match the case exactly. Windows is generally case-insensitive.
  • Permissions: Ensure the user running the script has read permissions for the file and execute permissions for all directories in the path.

Conclusion

FileNotFoundError: [Errno 2] No such file or directory means Python couldn't locate the file at the path you provided.

To fix it:

  1. Verify the file actually exists.
  2. Double-check the path for typos and correct case.
  3. Ensure the file extension is included.
  4. Use the correct absolute path OR construct the correct relative path from the script's current working directory (use os.getcwd() to check CWD).
  5. Use os.path.join() to build paths reliably across operating systems.
  6. Handle Windows paths correctly (raw strings r'' are recommended).
  7. Consider using os.path.exists() to check before opening if necessary.

By carefully specifying the correct path, you can reliably access files and avoid this common error.