91

How do I import a module(python file) that resides in the parent directory?

Both directories have a __init__.py file in them but I still cannot import a file from the parent directory?

In this folder layout, Script B is attempting to import Script A:

Folder A:
   __init__.py
   Script A:
   Folder B:
     __init__.py
     Script B(attempting to import Script A)

The following code in Script B doesn't work:

import ../scriptA.py # I get a compile error saying the "." is invalid
2
  • Not exactly answering your question, but if you run init.py inside Folder A and try and import Folder B or Script B, Script A will be successfully imported inside Script B. Commented Jan 21, 2012 at 7:01
  • Possible duplicate of Importing modules from parent folder Commented Nov 1, 2019 at 12:54

4 Answers 4

84

You don't import scripts in Python you import modules. Some python modules are also scripts that you can run directly (they do some useful work at a module-level).

In general it is preferable to use absolute imports rather than relative imports.

toplevel_package/
├── __init__.py
├── moduleA.py
└── subpackage
    ├── __init__.py
    └── moduleB.py

In moduleB:

from toplevel_package import moduleA

If you'd like to run moduleB.py as a script then make sure that parent directory for toplevel_package is in your sys.path.

Sign up to request clarification or add additional context in comments.

10 Comments

And why shouldn't sys path "hacks" be used in this case? Python makes it so hard to do what you want here without them. What exactly is the downside here?
@BT «sys.path.append(path_to_parent)» shouldn't be an answer to how to fix «"import ../scriptA.py # I get a compile error saying the "." is invalid"» question. There are cases where changing sys.path could be useful e.g., if python itself'd done it or a 3-party module that handles all corner cases correctly done it e.g., import autopath; autopath.add_toplevel_to_syspath() that automatically adds parent directory of toplevel_package to sys.path to allow a direct internal module execution as a script (or in a REPL) from any directory without proper PYTHONPATH or (virtualenv) install.
@J.F.Sebastian Is there some kind of proposal for a feature that allows us to explicit say what is the main folder or package of the whole project so that we don't have to care about adding parent directories to sys.path so that we can run submodules also as main files or scripts? I have a project where I really need to run scripts both as main or as modules, that is imported, but I need to do tons of hacks adding paths to sys.path to make them work in both cases. Would work in a virtualenv or using setuptools work somehow? I am really struggling with this...
@nbro the feature is called pip install main-package. You can run "submodules" already (just use their absolute names e.g., python -ma.b.c). If it is unclear; ask
This solution doesn't work for me. It raises: "ImportError: No module named toplevel_package"
|
37

From the docs:

from .. import scriptA

You can do this in packages, but not in scripts you run directly. From the link above:

Note that both explicit and implicit relative imports are based on the name of the current module. Since the name of the main module is always "__main__", modules intended for use as the main module of a Python application should always use absolute imports.

If you create a script that imports A.B.B, you won't receive the ValueError.

6 Comments

ValueError: Attempted relative import in non-package
@jgritty, that's because you're doing it in a script that you're running directly.
Yes, you're right. It will work if you call a script that then imports Script B.
@jgritty sys.path.append("..") is what you're looking for
Finally, 6 years later, the code snippet I've been looking for!
|
6

If you want to run the script directly, you can:

  1. Add the FolderA's path to the environment variable (PYTHONPATH).
  2. Add the path to sys.path in the your script.

Then:

import module_you_wanted

Comments

0

I struggled same kind of issue, and published syspend module on PyPI https://pypi.org/project/syspend/ This searches parent directories which have specific named file, and calls sys.path.append(directory: which has SYSPEND_ROOT file).

Folder A:
   __init__.py
   Script A:
   Folder B:
     __init__.py
     Script B(attempting to import Script A)
   SYSPEND_ROOT

In your case, please put SYSPEND_ROOT file. Empty file is OK. In your ScriptB.py

import syspend
import ScriptA

if __name__ == "__main__":
    ScriptA.method()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.