138

What is the correct way to fix this ImportError error?

I have the following directory structure:

/home/bodacydo
/home/bodacydo/work
/home/bodacydo/work/project
/home/bodacydo/work/project/programs
/home/bodacydo/work/project/foo

And I am in the directory

/home/bodacydo/work/project

Now if I type

python ./programs/my_python_program.py

I instantly get

ImportError: No module named foo.tasks

The ./programs/my_python_program.py contains the following line:

from foo.tasks import my_function

I can't understand why python won't find ./foo/tasks.py - it's there.

If I do it from the Python shell, then it works:

python
>>> from foo.tasks import my_function

It only doesn't work if I call it via python ./programs/my_python_program.py script.

eric
  • 7,142
  • 12
  • 72
  • 138
bodacydo
  • 75,521
  • 93
  • 229
  • 319

7 Answers7

149

Python does not add the current directory to sys.path, but rather the directory that the script is in. Add /home/bodacydo/work/project to either sys.path or $PYTHONPATH.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 11
    So whats the point then of having __init__.py in the root folder? It seems to serve no purpose if you edit either sys.path or the pythonpath. –  Jan 04 '14 at 23:13
  • 12
    @Editor: `__init__.py` only indicates that the directory should be treated as a package, when its parent is either in `sys.path` or is itself a package. – Ignacio Vazquez-Abrams Jan 04 '14 at 23:15
  • 5
    In addition check the permissions on the folder. That was the problem in my case. – SidJ Aug 24 '16 at 03:08
  • tried both still not working, I am using python 2.7 on macOs Sierra(10.12). – ishandutta2007 Jan 10 '17 at 04:39
  • 24
    To add current dir to python path, use `export PYTHONPATH=\`pwd\`` – rodorgas May 02 '17 at 21:39
  • 3
    What worked for me was to add to $PYTHONPATH the parent directory of the project, in your case will be: `/home/bodacydo/work` ... [see this answer](https://stackoverflow.com/a/714070/3404438) – maledr53 Jun 03 '17 at 22:22
38

Do you have a file called __init__.py in the foo directory? If not then python won't recognise foo as a python package.

See the section on packages in the python tutorial for more information.

Dave Kirby
  • 25,806
  • 5
  • 67
  • 84
  • Thanks and yes, I had `__init__.py`. The problem this time was with `$PYTHONPATH`. Ignacio's solution worked. – bodacydo Feb 24 '10 at 13:08
  • 2
    The __init__.py files are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path. In the simplest case, __init__.py can just be an empty file – panofish Jan 14 '16 at 21:13
  • Thanks for saving me sometime. – timon_the_destroyer Mar 31 '17 at 13:24
11

A better fix than setting PYTHONPATH is to use python -m module.path

This will correctly set sys.path[0] and is a more reliable way to execute modules.

I have a quick writeup about this problem, as other answerers have mentioned the reason for this is python path/to/file.py puts path/to on the beginning of the PYTHONPATH (sys.path).

anthony sottile
  • 61,815
  • 15
  • 148
  • 207
9

Here is a step-by-step solution:

  1. Add a script called run.py in /home/bodacydo/work/project and edit it like this:

    import programs.my_python_program
    programs.my_python_program.main()
    

    (replace main() with your equivalent method in my_python_program.)

  2. Go to /home/bodacydo/work/project
  3. Run run.py

Explanation: Since python appends to PYTHONPATH the path of the script from which it runs, running run.py will append /home/bodacydo/work/project. And voilà, import foo.tasks will be found.

cyborg
  • 9,989
  • 4
  • 38
  • 56
8

Example solution for adding the library to your PYTHONPATH.

  1. Add the following line into your ~/.bashrc or just run it directly:

    export PYTHONPATH="$PYTHONPATH:$HOME/.python"
    
  2. Then link your required library into your ~/.python folder, e.g.

    ln -s /home/user/work/project/foo ~/.python/
    
kenorb
  • 155,785
  • 88
  • 678
  • 743
2

In my mind I have to consider that the foo folder is a stand-alone library. I might want to consider moving it to the Lib\site-packages folder within a python installation. I might want to consider adding a foo.pth file there.

I know it's a library since the ./programs/my_python_program.py contains the following line:

from foo.tasks import my_function

So it doesn't matter that ./programs is a sibling folder to ./foo. It's the fact that my_python_program.py is run as a script like this:

python ./programs/my_python_program.py

Jeroen Dierckx
  • 1,570
  • 1
  • 15
  • 27
quamrana
  • 37,849
  • 12
  • 53
  • 71
1

If you have this problem when using an instaled version, when using setup.py, make sure your module is included inside packages

setup(name='Your program',
    version='0.7.0',
    description='Your desccription',
    packages=['foo', 'foo.bar'], # add `foo.bar` here
Danon
  • 2,771
  • 27
  • 37