135

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?

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
Marty Wallace
  • 34,046
  • 53
  • 137
  • 200
  • 1
    I'd read the documentation first: http://docs.python.org/2/tutorial/modules.html#packages – Blender May 27 '13 at 20:19
  • Well you can't import the same file name you are working on. – squiguy May 27 '13 at 20:19
  • In which file are you doing `import main` ? – Aivar May 27 '13 at 20:20
  • 5
    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. – vmemmap May 30 '22 at 12:30
  • Does this answer your question? [Importing modules from parent folder](https://stackoverflow.com/questions/714063/importing-modules-from-parent-folder) – Dr Fabio Gori Sep 06 '22 at 09:43

7 Answers7

117

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
  • 7
    PEP 8: E402 module level import not at top of file – madladzen Aug 10 '20 at 18:47
  • 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://stackoverflow.com/a/68299898/281545 – Mr_and_Mrs_D Dec 17 '22 at 18:43
53

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.

0x90
  • 39,472
  • 36
  • 165
  • 245
  • the only solution to the question title at least – Minsky Jan 15 '21 at 09:03
  • 1
    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://stackoverflow.com/questions/25344841/sys-path-vs-path/64768294#64768294 – Ola Jul 11 '22 at 08:22
37

8 years late to the party - 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.

djvg
  • 11,722
  • 5
  • 72
  • 103
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
26

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.

Nam G VU
  • 33,193
  • 69
  • 233
  • 372
Lennart Regebro
  • 167,292
  • 41
  • 224
  • 251
  • 10
    Adding `__init__.py` you make your directories into packages not modules. – raben Feb 06 '14 at 22:57
  • 5
    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. – Minsky Jan 15 '21 at 09:08
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.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
  • 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. – Bryan Oakley May 27 '13 at 20:48
  • 3
    @BryanOakley: That falls under what I said about "placing them on the system path". – BrenBarn May 27 '13 at 20:49
  • 2
    + after going through lot of SOQ I realized that python is blind to look up in parent directories. – sakhunzai Feb 13 '18 at 10:23
  • 1
    @sakhunzai: This is by design, for code portability. – Forest Nov 08 '20 at 14:44
6

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.

Community
  • 1
  • 1
Andy Fraley
  • 1,043
  • 9
  • 16
-2

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)

StackUP
  • 1,233
  • 12
  • 22
  • 6
    This didn't work for me, `ValueError: Attempted relative import in non-package` – jigglypuff Sep 19 '17 at 03:29
  • 10
    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. – niels Jan 07 '19 at 15:22