Import file from parent directory?
Asked Answered
N

8

140

I have the following directory structure:

application
    tests
        main.py
    main.py

application/main.py contains some functions.

tests/main.py will contain my tests for these functions but I can't import the top level main.py. I get the following error:

ImportError: Import by filename is not supported.

I am attempting to import using the following syntax:

import main

What am I doing wrong?

Nationalize answered 27/5, 2013 at 20:17 Comment(5)
I'd read the documentation first: docs.python.org/2/tutorial/modules.html#packagesOutreach
Well you can't import the same file name you are working on.Weiland
In which file are you doing import main ?Stigmasterol
The fact that a simple task is so complicated in such a supported language is just frustrating. This post has been viewed 141k times and yet some of the answers don't work well.Rodomontade
Does this answer your question? Importing modules from parent folderDiseur
L
121

If you'd like your script to be more portable, consider finding the parent directory automatically:

import os, sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# import ../db.py
import db
Lim answered 29/5, 2015 at 18:20 Comment(2)
PEP 8: E402 module level import not at top of filePutput
There is a more serious issue here than the PEP8 one mentioned in the comment above - modifying the sys.path is rarely the solution and more often than not a bad hack - see my answer below https://mcmap.net/q/165690/-import-file-from-parent-directorySolleret
A
58

You must add the application dir to your path:

import sys
sys.path.append("/path/to/dir")
from app import object

Or from shell:

setenv PATH $PATH:"path/to/dir"

In case you use windows: Adding variable to path in windows.

Or from the command line:

set PATH=%PATH%;C:\path\to\dir

Please mind the diff between PYTHONPATH, PATH, sys.path.

Antimagnetic answered 27/5, 2013 at 20:21 Comment(2)
the only solution to the question title at leastDesiderata
sys.path and environment variable PATH are two completely different things, they are not equivalent as may your answer suggest. If you do the latter that may work for one machine and not work on the other without the exact same PATH setting. modifying sys.path from inside a python script isn't as intrusive as modifying PATH on the OS or OS user level. Diff between os.path, PythonPATH and PATH: https://mcmap.net/q/138350/-sys-path-vs-path/…Foley
S
48

8 years after - still most other answers here are still not correct unfortunately - apart LennartRegebro's (and BrenBarn's) which is incomplete. For the benefit of future readers - the OP should, first of all, add the __init__.py files as in

root
    application
        __init__.py
        main.py
        tests
            __init__.py
            main.py

then:

$ cd root
$ python -m application.tests.main # note no .py

or

$ cd application
$ python -m tests.main

Running a script directly from inside its package is an antipattern - the correct way is running with the -m switch from the parent directory of the root package - this way all packages are detected and relative/absolute imports work as expected.

Solleret answered 8/7, 2021 at 10:29 Comment(5)
Finally the correct answer. Thanks a lot!Linalool
Finally I find this answer. A lot of thanks.Tallow
I agree with init.py, but what if you're running from a web hosting environment and not from the terminal?Ludie
@Ludie in that case the environment should be configured to launch the interpreter using the -m switchSolleret
Only true working good answer on all the question posts about this. Thank youChenault
G
27

First of all you need to make your directories into packages, by adding __init__.py files:

application
    tests
        __init__.py
        main.py
    __init__.py
    main.py

Then you should make sure that the directory above application is on sys.path. There are many ways to do that, like making the application infto a package and installing it, or just executing things in the right folder etc.

Then your imports will work.

Grievance answered 27/5, 2013 at 20:55 Comment(2)
Adding __init__.py you make your directories into packages not modules.Vesicatory
As it is written this allows to import code from subfolders, nor parent folders, and it's not an answer. Though it's helpful anyways.Desiderata
U
9

You cannot import things from parent/sibling directories as such. You can only import things from directories on the system path, or the current directory, or subdirectories within a package. Since you have no __init__.py files, your files do not form a package, and you can only import them by placing them on the system path.

Underprop answered 27/5, 2013 at 20:21 Comment(4)
Saying without qualification that you cannot is a little strong. You can't do it without a little extra effort, but all you have to do is put the parent directory on the path and you can do it.Amphetamine
@BryanOakley: That falls under what I said about "placing them on the system path".Underprop
+ after going through lot of SOQ I realized that python is blind to look up in parent directories.Scrumptious
@sakhunzai: This is by design, for code portability.Burkle
E
7

To import a file in a different subdirectory of the parent directory, try something like this:

sys.path.append(os.path.abspath('../other_sub_dir'))
import filename_without_py_extension

Edit: Missing closing bracket.

Earthward answered 30/10, 2019 at 21:3 Comment(0)
C
3

All answers are slightly confusing for a python newbie like me who isn't making a package and is using pylint. Let me clear it up.

If the directory structure is:

application
    main.py
    /tests
        test.py

Here is how you import one method from main.py into test.py

Here is application/main.py

def add_nums(a, b):
    print(a + b)

def subtract_nums(a, b):
    print(a - b)

Here is application/tests/test.py

import sys

sys.path.append("..")
# or sys.path.append("/Users/full/path/to/file")

# pylint: disable=wrong-import-position
from main import add_nums
# pylint: enable=wrong-import-position
Chamkis answered 3/9, 2023 at 22:56 Comment(1)
Thanks, This is the only solution which worked for me.Micky
L
-1

in python . exists for same directory, .. for parent directory to import a file from parent directory you can use ..

from .. import filename (without .py extension)

Lait answered 26/8, 2015 at 1:32 Comment(2)
This didn't work for me, ValueError: Attempted relative import in non-packageVankirk
This is actually close, but not quite right: you can use from ..helper import something, that works with a file helper.py in the parent dir.Ignoramus

© 2022 - 2024 — McMap. All rights reserved.