Skip to content Skip to sidebar Skip to footer

Python Function Import Not Working In Django Using Spyder

My Django project has the following folder structure where controllers is where I keep all custom .py files: C:. │ db.sqlite3 │ manage.py │ ├───myApp │ │

Solution 1:

Q : "If I run this same import in Spyder" => do you mean in spyder's integrated python shell ? A : "correct"

Then it's to be expected.

In the functions.py module, you can use a relative import (and that's actually what you want) because it will be resolved relatively to the current module ("functions.py").

When you're in the interactive shell, you are NOT in a module that's part of a package so relative imports cannot work here, and you have to use an absolute import (or an import relative to your current working directory, which is supposed to be first in your sys.path - unless something (IDE or else) messed with it of course.

IOW:

  • in your module, keep the explicit relative import (which should always work AND resolve to the correct "helpers" module or sub-package)
  • in your shell, use a qualified path that matches your current sys.path

EDIT

I don't fully comprehend what you mean by both "explicit relative import" and "qualified path"

"explicit relative import" : from .helpers import foo - it's a relative import (relative to the functions module), and it's explicit (the syntax used explicitely means "look for a 'helpers' module or subpackage in the same package as me and at the same level")

"qualified path": well yes not the best possible formulation I guess. I meant a "more or less absolute" import using the full python qualified path from your package's top to your module. The point is that what constitutes "your package's top" depends on what's in your sys.path, which in turn might (or not, depending on a few factors) depend on your current working directory.

By default, python inserts the current directory in first position of your sys.path. Then it uses the sys.path to find modules or packages (warning: the path listed in sys.path should NOT be the full path to your packages, but path to the directories containing your packages).

IOW, if you open a terminal, cd to your django's project root directory and launch a (standard) python shell, your project's root will come first in sys.path and the qualified name to your helpers module will be myapps.controllers.helpers. But if you were in myapps instead then the full path would be controllers.helpers...

The only sane way is actually to make sure you never have any of your project's packages path directly in your sys.path (IOW to always run your code from the project's root). This not only solves those pesky import issues, but also avoids the infamous "double import trap"

"In the functions.py module, you can use a relative import". You mean I can use the .?

Yes. Actually you even should use it unless you have a compelling reason not to, as it will prevent potential shadowing of the helpers module by another module by the same name that would come before in your sys.path - and it makes very explicit which helpers module or package you're importing from.

This is what I am doing in Scenario 1 and it does not work in Spyder.

As I already mentionned in a comment, "does not work in Spyder" is not enough to tell exactly what's wrong, because we don't know exactly what you're doing that "does not work in Spyder" - nor the exact error message AND full traceback FWIW, both of which are usually required for "does not work" questions (unless the issue is obvious of course).

But if it's (as I understood it) "launching a python shell in Spyder and typing from . helpers import xxx" then it will indeed not "work" - you can only use this syntax in module code, AND the module has to be part of a package, AND the directory containing this package has to be in your sys.path.

Which is why, in a python shell, you must use an absolute import ("from xxx import yyy"). But then, which exact path depends on what's in your sys.path - which partly depends on your current working directory (at least for a plain Python shell - I don't use Spyder so I can't tell what it's doing behind your back).

Now if Spyder is not totally braindead, it should use your django project's root as first element in sys.path (or at least have this directory in sys.path), so the full qualified path (from myapp.controllers.helpers import foo) should work. If it doesn't, check your cwd (os.getcwd()) and your sys.path, and edit your question with:

  • a complete description of what you were doing exactly
  • the exact error message and full traceback
  • your cwd and sys.path

Also, you probably want to read some documentation on Python's import system - which, to be fair, can be a king size PITA sometimes.

Solution 2:

A Try Except clause should do it:

try:
    from .helpers import foo
except ImportError:
    from helpers import foo

Post a Comment for "Python Function Import Not Working In Django Using Spyder"