7

Here is my app structure:

foodo/
    setup.py
    foodo/
        __init__.py
        foodo.py
        models.py

foodo/foodo/foodo.py imports classes from the models.py module:

from foodo.models import User

which throws an ImportError:

ImportError: No module named models

However, it does work if I use a relative import:

from models import User

And it also works if I put in an pdb breakpoint before the import and continue.

I should be able to use both absolute and relative imports right?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
LaSmell
  • 151
  • 8
  • How are you running `foodo/foodo/foodo.py`? If you've changed directory into `foodo/foodo/` and run `python foodo.py`, you'll get the behavior you describe. Instead, cd into `foodo/` and run `python -m foodo.foodo` and everything should work as intended. (You may additionally need `from __future__ import absolute_imports`, since the package and inner module name are the same.) – Blckknght Aug 21 '16 at 20:48
  • Hi thanks, yes __future__ works. So my options are to use this or relative imports? – LaSmell Aug 22 '16 at 20:13
  • Yes, you are also correct that renaming the inner foodo module fixes the issue and I can use the absolute import. Thanks – LaSmell Aug 22 '16 at 20:30

1 Answers1

7

You have a local module foodoo inside the foodoo package. Imports in Python 2 always first look for names in the current package before looking for a top-level name.

Either rename the foodoo module inside the foodoo package (eliminating the possibility that a local foodoo is found first) or use:

from __future__ import absolute_import

at the top of your modules in your package to enable Python-3 style imports where the top-level modules are the only modules searched unless you prefix the name with . to make a name relative. See PEP 328 -- Imports: Multi-Line and Absolute/Relative for more details.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Hi thanks, I renamed foodo/foodo/foodo.py to foodo/foodo/main.py but to no avail. I also tested by creating a dummy directory with all unique package/module names, but also got the error – LaSmell Aug 21 '16 at 20:24
  • @LaSmell: are you certain that a) you cleared all stale `.pyc` files or b) used entirely new names that you are guaranteed to not have `.pyc` files for? I can reproduce your issue exactly and fix it with using `from __future__ import absolute_imports` in *each module* in the package that needs to be able to do imports from the package. – Martijn Pieters Aug 21 '16 at 20:30
  • Yes I did both (a) and (b). I'm definitely doing something wrong here . . . The __future__ doesn't work on my test package/modules either Just to clarify, the top level foodo dir doesn't have an __init__, the foodo package does (/foodo/foodo/__init__.py) – LaSmell Aug 21 '16 at 20:41
  • @LaSmell: yes, that's clear. Are you by any chance trying to run a module in the package as a script? You can't do that, as that would mean the file is 'imported' as `__main__` and has no context of a package. – Martijn Pieters Aug 21 '16 at 20:58
  • no i'm not running a module in the package as a script. I'm installing the 'foodo' package via setup.py distutils (packages=['foodo']), which installs the foodo package (with all modules) to the virtual envs python site-packages dir and puts the executable 'foodo' script in the /usr/bin where the package is imported and executed. – LaSmell Aug 22 '16 at 20:00
  • Hi thanks, yes __future__ works, I'm just after trying there. So my options are to use this or relative imports? – LaSmell Aug 22 '16 at 20:13
  • @LaSmell: yes, in Python local names trump top-level names unless you use `from __future__ import absolute_imports` and in your case you can't use anything but such implicit relative imports if you used the same name as the top-level package. – Martijn Pieters Aug 22 '16 at 20:23
  • Thanks Martin, you were correct with you first answer: renaming the inner foodo module solved my issue and I was able to use the absolute import. Between @Blckkngt above and yourself I found what was catching me: 1. Don't execute package modules as scripts 2. Local module names trump packages if they are the same unless you are explicit with __future__ . Thanks so much guys, I learned a lot. – LaSmell Aug 22 '16 at 20:35
  • Minor syntax comment: should it be`from __future__ import absolute_import` (singular import, no `s` at end)? – NickBraunagel Dec 04 '17 at 19:59