FULL PYTHON FIX · 6 MIN READ

FileNotFoundError When the File Exists: Check Your Working Directory

A relative filename is resolved from the process working directory, which may differ from the script's folder. Print both paths, then choose an explicit location for the data file.

Quick fix

If the data file belongs beside your script, anchor the path to that script's directory.

PYTHON
from pathlib import Path

data_file = Path(__file__).resolve().parent / 'data' / 'notes.txt'
print(data_file.read_text(encoding='utf-8').strip())
See why this works and test the edge cases

Video guide: FileNotFoundError When the File Exists: Check Your Working Directory

The preview is stored on this site. YouTube loads only when you press Play. Watch on YouTube

Read the video transcript

Select a timestamp to watch that moment on YouTube.

  1. 00:00

    You can see a data file beside your script in a project folder, but Python still reports FileNotFoundError. How can a file exist and be missing at the same time? The answer is usually that the code and the human are starting from different locations. In this episode the script lives inside an app folder. Its notes file lives in an app data folder. We will run the script from the project root, use a relative path that looks plausible, and observe the failure. Then we will print the current working directory and the script location, build the file path from the script location, and rerun from two different folders. Pause and predict what a bare path like data slash notes dot text means to Python.

  2. 00:44

    Does it start at the script's folder, or at the working directory of the process that launched Python? The actual run will settle the question. The project root and the script folder are both real directories. The error does not mean the operating system has lost the file; it means the exact path Python constructed did not point to that file. The original code uses Path with data slash notes dot text, calls read text, and strips the trailing newline. We run app slash main dot py while the terminal is in the project root. Python raises FileNotFoundError. The traceback points to the read text call, and the missing path in the message is the bare relative path we supplied.

  3. 01:27

    It does not say that app slash data slash notes dot text is absent. That distinction is important. A relative path is a request to look somewhere relative to a base directory. Our code has not specified the base explicitly, so file operations use the process working directory. In this run that directory is the project root. Python looks for project root slash data slash notes dot text. The actual file is project root slash app slash data slash notes dot text. The two paths differ by one folder, which is enough for the lookup to fail. Look at the path displayed in the final exception line.

  4. 02:07

    That is the path argument given to read text, not a guarantee about where the file is. Compare it with the path you can see in the file tree. Add two diagnostic prints. Path dot cwd reports the current working directory. Path of underscore underscore file underscore underscore resolves the location of the running script, and parent gives its containing folder. In our demonstration the first path is the project root and the second path is the app folder. These are not interchangeable. The file on disk is beside the script, while the program looked beside the terminal's current directory. You can inspect a candidate path with exists or is file before opening it, but treat that as a diagnostic, not a reason to silently ignore missing data.

  5. 02:57

    Also remember that different launchers set the working directory differently. Running a script from an editor, a test runner, a scheduled task, or a server process can change Path dot cwd without moving the script itself. A path that works only when you launch from one folder is fragile unless that folder is an explicit part of your program's contract. The diagnostic prints are useful because launch tools may quietly set a working directory. Do not infer it from the editor tab or the script filename. Ask the process to print Path dot cwd at runtime. The file is intended to be shipped with this script, so build its path from the script directory.

  6. 03:39

    Path of underscore underscore file underscore underscore dot parent gives app. Joining data and notes dot text gives the actual fixture path. Run the corrected program from the project root. The terminal prints Python is fun. The file contents did not change; the lookup location changed. In a larger package, you may use package resources instead of assuming files live beside a script, but the principle remains the same: choose the correct base for the resource. If the user chooses a file at runtime, an absolute path or a path relative to a documented user folder may be more appropriate.

  7. 04:19

    Do not prepend the script directory blindly to every path. Ask what the path represents and who controls it. For this bundled notes file, a script-relative path accurately expresses our intention. The slash operator on Path objects joins path components in a way that works across operating systems. It is clearer than manually concatenating separators into one string. For this lesson, the resource is bundled beside the script. To verify that the fix is robust, run the same script while the terminal's working directory is somewhere else. The working directory printed by Path dot cwd changes, but the path derived from underscore underscore file underscore underscore still points beside the script.

  8. 05:06

    Ask is file about that full path and observe True. Then read it again and get the same text. This tests the cause rather than merely repeating one successful launch. For practice, create a small project with a script in one folder and a text file in a subfolder. First write a bare relative path and run it from two directories. Record which launch fails and why. Then use pathlib to build a path from the script location and test both launches again. If your own code still fails, print the resolved path, not just the short string you typed, and check case and file extension on disk. The Files lesson on PythonLessonLab gives you more examples of reading and writing safely.

  9. 05:51

    An is file check can confirm the path in a test, but a program still needs to decide what to do if the required resource is genuinely missing. It might report a clear setup error rather than continuing with incomplete data.

The file is beside the script, yet the lookup fails

Suppose a project contains app/main.py and app/data/notes.txt. From the project root you run python app/main.py. The script tries to open data/notes.txt, and Python reports FileNotFoundError even though you can see the file inside app/data.

The file exists, but the requested path points somewhere else. The bare relative path data/notes.txt is interpreted from the process's current working directory. In this run that means project/data/notes.txt, not project/app/data/notes.txt. A file manager showing a nearby file does not prove that Python is looking in that directory.

Project layout and failing command
PROJECT / TERMINAL
project/
  app/
    main.py
    data/notes.txt

# Run from project/:
python app/main.py
ERROR (LAST LINE)
FileNotFoundError: [Errno 2] No such file or directory: 'data/notes.txt'
The failing code in app/main.py
PYTHON
from pathlib import Path
print(Path('data/notes.txt').read_text(encoding='utf-8').strip())
LOOKUP LOCATION
project/data/notes.txt (not project/app/data/notes.txt)

Print the two directories before changing the path

Path.cwd() shows the process working directory. Path(__file__).resolve().parent shows the directory containing a normal Python script. Print them together, then print the absolute path your current expression would try to read. This turns a vague missing-file error into a specific path mismatch.

Your working directory depends on how the program was launched: terminal location, editor configuration, test runner, scheduler, or service. It is not guaranteed to be the folder containing the script. The __file__ variable is available in a script file, but may not exist in a REPL or some notebook environments; those contexts need a separately configured data path.

Inspect the actual locations
PYTHON
from pathlib import Path
print('Working directory:', Path.cwd())
print('Script directory:', Path(__file__).resolve().parent)
print('Requested file:', Path('data/notes.txt').resolve())
WHAT TO LOOK FOR
The requested file may point to project/data/notes.txt while the real file is under project/app/data/notes.txt.

Build a path relative to the script

If the data file belongs beside your script, anchor the path to that script's directory. Path(__file__).resolve().parent locates app; the / operator joins its data folder and filename. Now the path has the same meaning regardless of where the terminal started.

Choose the anchor deliberately. For a file selected by the user or a project-wide configuration file, a fixed script-relative path may be the wrong design. In those cases accept a path argument or configure a project data directory. The fix here matches the stated layout: a bundled data file stored beside the script.

Reliable app/main.py
PYTHON
from pathlib import Path

data_file = Path(__file__).resolve().parent / 'data' / 'notes.txt'
print(data_file.read_text(encoding='utf-8').strip())
OUTPUT
Python is fun.

Run from a different directory

The best test of a script-relative path is to launch the same file from another working directory. The output should remain the same. You can also check data_file.is_file() before reading, then print data_file.resolve() if it is false. That gives a concrete path to inspect rather than a generic error.

An absolute path is useful for diagnosis, but hard-coding one person's home folder is a fragile final solution. Likewise, changing the process working directory merely to make one read work can affect other relative paths. Pathlib lets you state which file you mean without changing global process state.

Check the path your program will read
PYTHON
from pathlib import Path

data_file = Path(__file__).resolve().parent / 'data' / 'notes.txt'
print(data_file.is_file())
print(data_file.read_text(encoding='utf-8').strip())
OUTPUT
True
Python is fun.
  • Run app/main.py from the project root and from app/; the corrected path should work both times.
  • If is_file() is false, print the absolute path and compare it with the actual file.
  • For notebook code, pass in or configure the data directory because __file__ may be unavailable.

Practice the fix

Create app/data/message.txt and app/main.py. Make the script print Path.cwd(), then read the file using a path built from Path(__file__).resolve().parent. Run the script from both the project root and the app directory.

Need a hint?

Use Path(__file__).resolve().parent / 'data' / 'message.txt'. Compare the two cwd values while confirming the read result stays the same.

Python console

Ready to run

This browser console runs separate, in-browser Python. Use your local terminal for this guide’s project files, packages, and environment commands.

Does your code use input()? Add one value per line
Ctrl / ⌘ + Enter to run
OUTPUT
Your output appears here.

Key takeaways

  • Relative paths resolve from the process working directory, not automatically from the script folder.
  • Print Path.cwd(), the script directory, and the resolved requested path to diagnose a mismatch.
  • Anchor bundled data to Path(__file__).resolve().parent when the data lives beside the script.
  • Test from more than one working directory and choose another anchor for user-supplied paths.

What to do next

  1. Review the prerequisite: Reading and Writing Files.
  2. Prove it yourself: Pass the checked task in Reading and Writing Files.
  3. Use it in a project: Open a local CSV from a known path, then run the project source on GitHub .

Related lessons

Sources and further reading