[python] Python: importing a sub-package or sub-module

Having already use flat packages, I was not expecting the issue I encountered with nested packages. Here is…

Directory layout

dir
 |
 +-- test.py
 |
 +-- package
      |
      +-- __init__.py
      |
      +-- subpackage
           |
           +-- __init__.py
           |
           +-- module.py

Content of init.py

Both package/__init__.py and package/subpackage/__init__.py are empty.

Content of module.py

# file `package/subpackage/module.py`
attribute1 = "value 1"
attribute2 = "value 2"
attribute3 = "value 3"
# and as many more as you want...

Content of test.py (3 versions)

Version 1

# file test.py
from package.subpackage.module import *
print attribute1 # OK

That's the bad and unsafe way of importing things (import all in a bulk), but it works.

Version 2

# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
from module import attribute1

A safer way to import, item by item, but it fails, Python don't want this: fails with the message: "No module named module". However …

# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
print module # Surprise here

… says <module 'package.subpackage.module' from '...'>. So that's a module, but that's not a module /-P 8-O ... uh

Version 3

# file test.py v3
from package.subpackage.module import attribute1
print attribute1 # OK

This one works. So you are either forced to use the overkill prefix all the time or use the unsafe way as in version #1 and disallowed by Python to use the safe handy way? The better way, which is safe and avoid unecessary long prefix is the only one which Python reject? Is this because it loves import * or because it loves overlong prefixes (which does not help to enforce this practice)?.

Sorry for the hard words, but that's two days I trying to work around this stupid-like behavior. Unless I was totally wrong somewhere, this will leave me with a feeling something is really broken in Python's model of package and sub-packages.

Notes

  • I don't want to rely on sys.path, to avoid global side effects, nor on *.pth files, which are just another way to play with sys.path with the same global effets. For the solution to be clean, it has to be local only. Either Python is able to handle subpackage, either it's not, but it should not require to play with global configuration to be able to handle local stuff.
  • I also tried use imports in package/subpackage/__init__.py, but it solved nothing, it do the same, and complains subpackage is not a known module, while print subpackage says it's a module (weird behavior, again).

May be I'm entirely wrong tough (the option I would prefer), but this make me feel a lot disappointed about Python.

Any other known way beside of the three I tried? Something I don't know about?

(sigh)

----- %< ----- edit ----- >% -----

Conclusion so far (after people's comments)

There is nothing like real sub-package in Python, as all package references goes to a global dictionnary, only, which means there's no local dictionary, which implies there's is no way to manage local package reference.

You have to either use full prefix or short prefix or alias. As in:

Full prefix version

from package.subpackage.module import attribute1
# An repeat it again an again
# But after that, you can simply:
use_of (attribute1)

Short prefix version (but repeated prefix)

from package.subpackage import module
# Short but then you have to do:
use_of (module.attribute1)
# and repeat the prefix at every use place

Or else, a variation of the above.

from package.subpackage import module as m
use_of (m.attribute1)
# `m` is a shorter prefix, but you could as well
# define a more meaningful name after the context

Factorized version

If you don't mind about importing multiple entity all at once in a batch, you can:

from package.subpackage.module import attribute1, attribute2
# and etc.

Not in my first favorite taste (I prefer to have one import statement per imported entity), but may be the one I will personally favor.

Update (2012-09-14):

Finally appears to be OK in practice, except with a comment about the layout. Instead of the above, I used:

from package.subpackage.module import (

    attribute1, 
    attribute2,
    attribute3,
    ...)  # and etc.

This question is related to python import module package

The answer is


If all you're trying to do is to get attribute1 in your global namespace, version 3 seems just fine. Why is it overkill prefix ?

In version 2, instead of

from module import attribute1

you can do

attribute1 = module.attribute1

The reason #2 fails is because sys.modules['module'] does not exist (the import routine has its own scope, and cannot see the module local name), and there's no module module or package on-disk. Note that you can separate multiple imported names by commas.

from package.subpackage.module import attribute1, attribute2, attribute3

Also:

from package.subpackage import module
print module.attribute1

Examples related to python

programming a servo thru a barometer Is there a way to view two blocks of code from the same file simultaneously in Sublime Text? python variable NameError Why my regexp for hyphenated words doesn't work? Comparing a variable with a string python not working when redirecting from bash script is it possible to add colors to python output? Get Public URL for File - Google Cloud Storage - App Engine (Python) Real time face detection OpenCV, Python xlrd.biffh.XLRDError: Excel xlsx file; not supported Could not load dynamic library 'cudart64_101.dll' on tensorflow CPU-only installation

Examples related to import

Import functions from another js file. Javascript The difference between "require(x)" and "import x" pytest cannot import module while python can How to import an Excel file into SQL Server? When should I use curly braces for ES6 import? How to import a JSON file in ECMAScript 6? Python: Importing urllib.quote importing external ".txt" file in python beyond top level package error in relative import Reading tab-delimited file with Pandas - works on Windows, but not on Mac

Examples related to module

How to fix: fatal error: openssl/opensslv.h: No such file or directory in RedHat 7 How to import functions from different js file in a Vue+webpack+vue-loader project Typescript ReferenceError: exports is not defined ImportError: No module named tensorflow ModuleNotFoundError: What does it mean __main__ is not a package? ES6 modules in the browser: Uncaught SyntaxError: Unexpected token import module.exports vs. export default in Node.js and ES6 What's the difference between an Angular component and module Export multiple classes in ES6 modules Python - Module Not Found

Examples related to package

ModuleNotFoundError: No module named 'sklearn' Python: How to pip install opencv2 with specific version 2.4.9? Relative imports - ModuleNotFoundError: No module named x Is __init__.py not required for packages in Python 3.3+ "pip install unroll": "python setup.py egg_info" failed with error code 1 Unable to Install Any Package in Visual Studio 2015 beyond top level package error in relative import How can I specify the required Node.js version in package.json? "installation of package 'FILE_PATH' had non-zero exit status" in R Error in installation a R package