Nick T
Nick T

Reputation: 26717

How can I import a package from within the package?

I'm writing a little package and I'm trying to include a demo script within it as an example. However, I can't seem to import the package cleanly from within as though I was outside of it.

With a directory structure like:

trainer/
  __init__.py
  helper.py
  trainer.py
  [...more files...]
  demo.py

In demo.py I can't do from .. import trainer as it complains "Attempted relative import in non-package", despite the __init__.py. If I move the demo up a directory and import trainer it works fine, but I was trying to keep it together with the package.

The hack-looking import __init__ as trainer works, but eeeew.

Importing the various bits from all over the module directly also works, but makes for a messy example. Am I wholly misguided in my attempt or is there a better solution?

Upvotes: 1

Views: 227

Answers (2)

voithos
voithos

Reputation: 70552

If you're trying to run demo.py as python demo.py, the problem that you're having is likely the same as here.

What's happening is that Python's relative import mechanism works by using the __name__ of the current module. When you execute a module directly, the __name__ gets set "__main__" regardless what the actual module name is. Thus, relative (in-package) imports don't work.

To remedy this, you can do the following:

  • Execute demo.py as a module within a package, like so: python -m trainer.demo. This should fix the error, but you'll still be importing the trainer.py module instead of the package.

  • Now add from __future__ import absolute_import to demo.py, which will cause your imports to be absolute-only by default, meaning that relative imports have to explicit (as in, from . import (...)). This is force import trainer to import the entire top-level package, instead of the module.

Upvotes: 2

Hai Vu
Hai Vu

Reputation: 40688

The way you organize the files, demo.py becomes part of the package, which might or might not be what you want. You can organize your files a little differently, moving demo.py outside of the trainer directory:

TopDir/
    demo.py
    trainer/
    __init__.py
    helper.py
    trainer.py
    [... more files ...]

Then, demo.py can do something like:

from trainer import trainer, helper

Upvotes: 0

Related Questions