Skip to content

How to Create File Paths with Variables in Python

Learn how to build dynamic, cross-platform file paths in Python using pathlib and os.path.join to avoid hardcoding and ensure compatibility across Windows, Linux, and macOS.

Hardcoding file paths like "C:\Users\Davide\data" creates fragile code that breaks the moment it runs on a different machine or operating system. A path that works perfectly on Windows will fail on Linux or macOS, and vice versa. The solution is to use variables combined with proper path-joining techniques, ensuring your code remains cross-platform, maintainable, and resilient to change.

This guide covers every practical approach to building dynamic file paths in Python, from the modern pathlib module to the traditional os.path.join function, along with common mistakes to avoid.

Using pathlib for Modern Path Construction

The pathlib module, available since Python 3.4, provides an intuitive object-oriented API for filesystem paths. Its standout feature is the / operator, which joins path components while automatically using the correct separator for the current operating system:

from pathlib import Path

folder = Path("data")
year = "2026"
filename = "report.csv"

full_path = folder / year / filename

print(full_path)

You never need to think about whether to use \ or /. Python handles it for you.

Building Paths from Multiple Variables

Real-world projects often require assembling paths from several dynamic components. pathlib handles this cleanly regardless of how many segments you need:

from pathlib import Path

project = "analytics"
environment = "production"
version = "v2"
config_file = "settings.json"

config_path = Path("projects") / project / environment / version / config_file

print(config_path)

Each variable slots naturally into the path chain, making the resulting structure easy to read and modify.

Using the Home Directory

Referencing the user's home directory is a common requirement for configuration files, caches, and application data. pathlib provides a portable way to do this:

from pathlib import Path

home = Path.home()
app_data = home / ".myapp" / "config.yaml"

print(app_data)

The same code produces the correct path on every platform without any conditional logic.

Working with the Current Directory

You can build paths relative to either the current working directory or the directory containing the script itself:

from pathlib import Path

cwd = Path.cwd()
output_file = cwd / "output" / "results.json"

script_dir = Path(__file__).parent
data_file = script_dir / "data" / "input.csv"

Including Environment Variables

Environment variables let you externalize path configuration, which is especially useful in deployment pipelines and containerized environments:

from pathlib import Path
import os

data_root = os.environ.get("DATA_DIR", "/default/data")
user = os.environ.get("USER", "unknown")

log_path = Path(data_root) / "logs" / user / "app.log"

print(log_path)

The os.environ.get() call with a default value prevents KeyError exceptions when the variable is not set.

Using os.path.join for Legacy Code

Before pathlib existed, os.path.join was the standard way to build cross-platform paths. It remains valid and is still widely used in older codebases:

import os

username = "admin"
filename = "preferences.xml"

path = os.path.join("users", username, "settings", filename)

print(path)

You can also expand the user home directory with os.path.expanduser:

import os

path = os.path.join("~", "documents", "file.txt")
expanded = os.path.expanduser(path)

print(expanded)

Avoiding Common Mistakes

One of the most frequent errors is using string concatenation or f-strings to build file paths. While this might seem to work during development, it introduces cross-platform bugs and bypasses path normalization.

Wrong approach using string concatenation or f-strings:

year = "2026"
filename = "report.csv"

path = "data" + "/" + filename
print(path)

path = f"data/{year}/{filename}"
print(path)

Correct approach using pathlib or os.path.join:

from pathlib import Path
import os

year = "2026"
filename = "report.csv"

path = Path("data") / year / filename
print(path)

path = os.path.join("data", year, filename)
print(path)

Creating Directories Along the Path

When constructing a path to a file that does not exist yet, you need to ensure all parent directories are created before writing:

from pathlib import Path

output_dir = Path("results") / "2026" / "quarterly"
output_file = output_dir / "q1_report.csv"

output_dir.mkdir(parents=True, exist_ok=True)

output_file.write_text("data,value\n")

The parents=True argument creates every missing directory in the chain, and exist_ok=True prevents an error if the directory already exists.

Converting Between Path Types

Some libraries and APIs still expect string paths rather than Path objects. Converting between the two is straightforward:

from pathlib import Path
import os

path = Path("data") / "file.txt"

path_string = str(path)
print(path_string)

from_string = Path("/some/path/file.txt")

basename = os.path.basename(path)
print(basename)

Building Paths from a List of Components

When path segments are stored in a list, for example read from a configuration file or built dynamically, you can unpack them directly:

from pathlib import Path
import os

components = ["data", "processed", "2026", "january", "report.csv"]

path = Path(*components)
print(path)

path = os.path.join(*components)
print(path)

The * unpacking operator passes each list element as a separate argument, which both Path() and os.path.join() handle correctly.

Method Comparison

Method Syntax Cross-Platform Best For
pathlib Path(a) / b Yes Modern Python (3.4+)
os.path.join join(a, b, c) Yes Legacy compatibility
f-strings f"{a}/{b}" Problematic Avoid for paths
Concatenation a + "/" + b No Never use

Conclusion

For all new Python code, prefer pathlib. It offers cleaner syntax through the / operator, reliable cross-platform behavior, and a comprehensive set of methods for every common path operation. Reserve os.path.join for maintaining legacy codebases, and avoid string concatenation or f-strings for path construction entirely. Building paths with variables the right way saves you from subtle, hard-to-debug issues that only surface when your code runs on a different machine or operating system.

Navigation