Desk Clarity

Everyday document & browser help

Python finds a data file only from one folder: inspect cwd before changing the path

By ON Lab · Sources checked November 8, 2026

A relative data-file path is normally interpreted from the process's current working directory, not automatically from the directory containing the Python source file. Print Path.cwd() and inspect the intended file before adding more ../ segments. For data deliberately stored beside source files, build a path from that source file's location; for caller-supplied input, keep the input contract explicit.

The historical reader project had a data directory next to a package directory. A relative file operation worked when launched inside the package but failed when the main program was launched from its parent. We checked current pathlib documentation and reproduced that directory distinction with a small local project. We did not run the reader's Windows project.

Observe both locations

from pathlib import Path

print("working directory:", Path.cwd())
print("source file:", Path(__file__).resolve())

candidate = Path("../data/test.txt")
print("candidate:", candidate.resolve())
print("exists:", candidate.exists())

Use this in an ordinary saved Python file in the execution route that fails. An interactive prompt or notebook may not define __file__; do not copy this anchor unchanged into such a context. Resolving a path helps inspect the location but does not create the file or repair permissions.

The spelling of a parent path also matters. A parent component is .. followed by a path separator or another path component operation. A filename beginning with dots is not necessarily a parent traversal. Read the actual error and the actual constructed path rather than assuming the editor's project panel defines the process directory.

Our three-location comparison

We created this disposable layout, with a file containing one known line:

project/
    data/test.txt
    package/probe.py
other/

Inside probe.py we compared Path("../data/test.txt") with an anchor made from the saved source file:

source = Path(__file__).resolve()
project_root = source.parent.parent
anchored = project_root / "data" / "test.txt"
print(anchored.read_text(encoding="utf-8"))
Launch directoryRelative candidate existsAnchored read
projectNoExpected data
project/packageYesExpected data
otherNoExpected data

The interpreter received the same saved script path in all three launches. Changing only the working directory changed the relative candidate's result. The explicit source anchor selected the same file each time. Our fixture used a UTF-8-compatible ASCII marker and checked the actual content, rather than treating file existence alone as a successful read.

Choose the base that matches the file's role

For a small source checkout whose layout is intentionally fixed, the source-file anchor can be appropriate. The two parent operations above are specific to the displayed layout. Do not treat parent.parent as a universal project-root detector. Moving the source file changes that relationship.

For a user-selected input file, an argument or configuration value can be the right contract. If relative inputs are defined relative to the caller's working directory, preserve that meaning. Forcing every input to be relative to the script could make a previously correct command read the wrong file.

For data installed as part of a reusable package, review that package's resource-loading approach. A source-tree location is not a guarantee about a built wheel, zipped package or frozen application. This guide does not test those deployment formats and does not present the checkout anchor as a universal installed-package solution.

Do not change the whole process directory to hide the issue

Changing the working directory can change every later relative file operation, including logging, output and child process inputs. Prefer constructing an explicit path for the operation unless the application deliberately defines a new working directory as part of its contract.

An IDE can also launch a program with a configured working directory. Inspect the value printed by the actual run, then check the run configuration if it differs from your intended input convention. A setting visible in another terminal is not proof that the failing run uses it.

Verify the selected file and the failure that remains

  1. Print the actual working directory and constructed candidate.
  2. Confirm the intended file exists at that location.
  3. Read a small known value through the same code path.
  4. Launch the saved script from a second directory and compare results.
  5. Keep any permission, encoding or file-format error separate from a missing path.

A file can exist but still be unreadable or contain unexpected data. A successful anchored read proves the selected fixture file was found; it does not validate a real CSV schema or permission policy. Preserve the original error so a later change of symptom is visible.

If the error is instead that an installed Python module cannot be imported, use the interpreter and installation guide. Data-file path resolution and module installation are different investigations, even when an editor makes both appear to depend on where a program is launched.

Checked November 8, 2026. Three launch directories were tested locally with Python 3.9.6. Notebook, symlink deployment, packaged resource and original Windows behavior were not reproduced. The historical reader question is not evidence of current search volume.

Sources