I have frequently run into a common roadblock: trying to access a script located just one level up in the folder hierarchy.
It sounds like a simple task, but Python’s default module search path can be a bit stubborn when you are working with complex project structures.
In this tutorial, I will show you exactly how to handle these imports using the same techniques I use in my professional data architecture projects.
The Challenge with Parent Directory Imports
By default, Python looks for modules in the current directory, the standard library, and the site-packages folder.
If your script is tucked away in a subfolder and needs a utility file from the root, Python will usually throw a ModuleNotFoundError.
I have found that the best way to explain this is through a real-world project structure rather than a simple “Hello World” script.
Our Project Structure: US Real Estate Analytics
Imagine we are building a tool to analyze housing market trends across different US states. Here is how our files are organized:
us_housing_project/
│
├── config.py # Contains US_STATES list and API_KEYS
│
└── analysis/
└── market_trend.py # We need to import config.py hereIn this scenario, market_trend.py needs to access the global configuration defined in config.py.
Method 1: Use the sys.path.append Technique
This is the easy “quick fix” I use when I need to bridge the gap between a subdirectory and a parent folder immediately.
By modifying sys.path at runtime, we tell the Python interpreter specifically where to look for our missing module.
The Code Example
Here is how I implement this to pull state-specific configurations into our analysis script:
import sys
import os
# Adding the parent directory to the system path
# '..' represents the directory above the current file
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
# Now we can import our config file
try:
import config
print("Successfully connected to the project configuration.")
except ImportError as e:
print(f"Connection failed: {e}")
def run_state_analysis(state_code):
"""Analyzes trends for a specific US state."""
if state_code in config.US_STATES:
print(f"Analyzing market data for: {state_code}")
# Imagine complex logic here using config.API_KEYS
else:
print("Invalid State Code.")
if __name__ == "__main__":
# Testing with a specific US state
run_state_analysis("NY")You can see the output in the screenshot below.

I prefer this method for small scripts or internal tools because it is highly explicit.
However, I always remind my junior developers that the order of sys.path matters; appending to the end ensures you don’t accidentally override standard library modules.
Method 2: The Modern Pathlib Approach
Since Python 3.4 was released, I have moved away from os.path in favor of the pathlib module.
It treats paths as objects rather than strings, which makes the code much cleaner and easier to read, especially on Windows vs. Linux systems.
The Code Example
In this example, we will use pathlib to navigate up to the parent directory to fetch our US market data settings.
from pathlib import Path
import sys
# Get the absolute path of the current file
current_file = Path(__file__).resolve()
# Get the parent directory (us_housing_project/)
parent_directory = current_file.parent.parent
# Add the parent to sys.path
sys.path.append(str(parent_directory))
# Import the parent module
import config
def display_census_region(state):
"""Prints the census region for a given US state from the config."""
regions = config.US_REGIONS # Assuming this exists in config.py
region = regions.get(state, "Unknown Region")
print(f"The state of {state} is in the {region} region.")
if __name__ == "__main__":
# Let's check a state like Texas
display_census_region("TX")You can see the output in the screenshot below.

I find this approach much more intuitive. Using .parent feels more natural than nesting os.path.dirname calls multiple times.
It is my go-to method for any modern Python 3 project that requires navigating complex file structures.
Method 3: Use Environment Variables (PYTHONPATH)
There are times when I don’t want to “pollute” my code with path manipulation logic.
In these cases, I use the PYTHONPATH environment variable. This tells Python to always include specific directories when searching for modules.
How to Set It Up
If you are working in a terminal (macOS/Linux or PowerShell in the US), you can set this before running your script.
For Mac/Linux:
export PYTHONPATH="${PYTHONPATH}:/path/to/us_housing_project"
python3 analysis/market_trend.pyFor Windows (PowerShell):
$env:PYTHONPATH += ";C:\path\to\us_housing_project"
python analysis\market_trend.pyI generally reserve this for production environments or CI/CD pipelines.
It keeps the Python source code clean, but you have to be careful that every developer on your team has their environment configured the same way.
Method 4: Convert the Project into a Package
If your project is growing, I highly recommend turning it into a formal Python package.
By adding __init__.py files, you can use relative imports (like from .. import config), provided you run the code as a module.
Updated Structure
us_housing_project/
│
├── __init__.py
├── config.py
│
└── analysis/
├── __init__.py
└── market_trend.pyThe Code Example
Inside market_trend.py, you can now use a relative import:
# analysis/market_trend.py
# Relative import from the parent directory
from .. import config
def calculate_mortgage_tax(loan_amount):
"""Calculates estimated tax based on US federal rates in config."""
tax_rate = config.FEDERAL_TAX_RATE
estimated_tax = loan_amount * tax_rate
print(f"Estimated Federal Tax: ${estimated_tax:,.2f}")
if __name__ == "__main__":
calculate_mortgage_tax(500000)Crucial Step: To run this without errors, you must execute it from the root folder using the -m flag: python -m analysis.market_trend
Common Pitfalls to Avoid
In my experience, many developers forget that relative imports only work if the script is part of a package.
If you try to run python analysis/market_trend.py directly while using from .. import config, you will receive a “top-level package” error.
Another tip: always use absolute paths when modifying sys.path. Using relative strings can lead to unpredictable behavior if you run the script from different locations.
Best Practices for Project Organization
When I architect databases or backend systems, I try to minimize the need for parent imports altogether.
Whenever possible, I place “entry point” scripts in the root directory and keep subdirectories strictly for library-like modules.
If you find yourself importing from a parent directory constantly, it might be a sign that your project structure needs a quick reorganization.
I hope you found this tutorial helpful! Importing from a parent directory is a hurdle every Python developer faces, but with these methods, you can choose the one that fits your specific workflow.
You may also like to read:
- How to Read a File Line by Line in Python
- Python Pass by Reference
- How to Convert a Python Dict to JSON
- Python TypeError: Can Only Concatenate str (Not “Bytes”) to str

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.