You seem to be misunderstanding how import searches for modules. When you use an import statement it always searches the actual module path (and/or sys.modules); it doesn't make use of module objects in the local namespace that exist because of previous imports. When you do:

import package.subpackage.module
from package.subpackage import module
from module import attribute1

The second line looks for a package called package.subpackage and imports module from that package. This line has no effect on the third line. The third line just looks for a module called module and doesn't find one. It doesn't "re-use" the object called module that you got from the line above.

In other words from someModule import ... doesn't mean "from the module called someModule that I imported earlier..." it means "from the module named someModule that you find on sys.path...". There is no way to "incrementally" build up a module's path by importing the packages that lead to it. You always have to refer to the entire module name when importing.

It's not clear what you're trying to achieve. If you only want to import the particular object attribute1, just do from package.subpackage.module import attribute1 and be done with it. You need never worry about the long package.subpackage.module once you've imported the name you want from it.

If you do want to have access to the module to access other names later, then you can do from package.subpackage import module and, as you've seen you can then do module.attribute1 and so on as much as you like.

If you want both --- that is, if you want attribute1 directly accessible and you want module accessible, just do both of the above:

from package.subpackage import module
from package.subpackage.module import attribute1
attribute1 # works
module.someOtherAttribute # also works

If you don't like typing package.subpackage even twice, you can just manually create a local reference to attribute1:

from package.subpackage import module
attribute1 = module.attribute1
attribute1 # works
module.someOtherAttribute #also works
Answer from BrenBarn on Stack Overflow
Top answer
1 of 4
112

You seem to be misunderstanding how import searches for modules. When you use an import statement it always searches the actual module path (and/or sys.modules); it doesn't make use of module objects in the local namespace that exist because of previous imports. When you do:

import package.subpackage.module
from package.subpackage import module
from module import attribute1

The second line looks for a package called package.subpackage and imports module from that package. This line has no effect on the third line. The third line just looks for a module called module and doesn't find one. It doesn't "re-use" the object called module that you got from the line above.

In other words from someModule import ... doesn't mean "from the module called someModule that I imported earlier..." it means "from the module named someModule that you find on sys.path...". There is no way to "incrementally" build up a module's path by importing the packages that lead to it. You always have to refer to the entire module name when importing.

It's not clear what you're trying to achieve. If you only want to import the particular object attribute1, just do from package.subpackage.module import attribute1 and be done with it. You need never worry about the long package.subpackage.module once you've imported the name you want from it.

If you do want to have access to the module to access other names later, then you can do from package.subpackage import module and, as you've seen you can then do module.attribute1 and so on as much as you like.

If you want both --- that is, if you want attribute1 directly accessible and you want module accessible, just do both of the above:

from package.subpackage import module
from package.subpackage.module import attribute1
attribute1 # works
module.someOtherAttribute # also works

If you don't like typing package.subpackage even twice, you can just manually create a local reference to attribute1:

from package.subpackage import module
attribute1 = module.attribute1
attribute1 # works
module.someOtherAttribute #also works
2 of 4
11

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
🌐
Reddit
reddit.com › r/learnpython › how to properly do imports when a project is a submodule of another?
r/learnpython on Reddit: How to properly do imports when a project is a submodule of another?
September 20, 2023 -

I have a project named ProjectA that I wrote that has a structure like this (__init__.py is present in all sub directories but not shown here):

  • main_file.py

  • libs/filea.py

  • libs/fileb.py

  • options/filec.py

  • classes/classa.py

  • classes/classb.py

  • functions/func1.py

  • functions/func2.py

The main_file.py will import or its imports will import part of every file listed above. I used absolute imports for each of those and it works great when I run python main_file.py.

Now I want to use what I wrote as a submodule for another project. It will be a simple script that imports a function from main_file.py (which in turn imports from all the files above).

What is the proper way to do the imports so that I can run both python main_file.py and use a function from main_file.py in another script? I know I can turn all of the imports in ProjectA into relative imports, is that the best way?

Discussions

Python submodule imports using __init__.py - Stack Overflow
I'm learning Python, and I can't figure out how imports in __init__.py work. I understand from the Python tutorial that the __init__.py file initializes a package, and that I can import subpackage... More on stackoverflow.com
🌐 stackoverflow.com
ModuleNotFoundError: No module named 'supermodule.submodule'; 'supermodule' is not a package
🐛 Bug Reports I am working for writing Python extension, but facing import submodule error. ModuleNotFoundError: No module named 'supermodule.submodule'; 'supermodule' is not a pack... More on github.com
🌐 github.com
28
February 8, 2020
git - How to structure Python modules so they are accesible from different submodules - Software Engineering Stack Exchange
If the various modules form a single ... ..foo import specific_function). For example, instead of this project layout: my-project/ scripts/ ... p_foo/ __init__.py p_bar/ __init__.py · I would expect a layout like this, without any Git submodules or similar: my-project/ p/ __init__.py __main__.py foo/ ... bar/ ... (The __main__.py file allows the module to be used as a command line tool like python3 -m MODULE ... More on softwareengineering.stackexchange.com
🌐 softwareengineering.stackexchange.com
May 17, 2021
How to import a submodule in Python? (without `exec`) - Stack Overflow
Since my question explicitly says importing a submodule, the answer from @Bakuriu is correct, however including this for completeness and it may help others who run into the same problem. More on stackoverflow.com
🌐 stackoverflow.com
May 24, 2017
🌐
Tenthousandmeters
tenthousandmeters.com › blog › python-behind-the-scenes-11-how-the-python-import-system-works
Python behind the scenes #11: how the Python import system works
July 13, 2021 - When Python imports a top-level module, it searches for the module in the directories and ZIP archives listed in sys.path. But when it imports a submodule, it uses the __path__ attribute of the parent module instead of sys.path.
🌐
Medium
elfi-y.medium.com › demystify-python-packages-and-modules-73dffd09ff84
Demystify Python Packages and Modules | by E.Y. | Medium
December 30, 2020 - Note that when using from package import item, the item can be either a submodule (or subpackage) of the package, or a function, class or variable. The import statement first tests whether the item is defined in the package; if not, it assumes ...
Top answer
1 of 3
38

You probably already understand that when you import a module, the interpreter creates a new namespace and executes the code of that module with the new namespace as both the local and global namespace. When the code completes execution, the module name (or the name given in any as clause) is bound to the module object just created within the importing namespace and recorded against its __name__ in sys.modules.

When a qualified name such as package.subpackage.module is imported the first name (package) is imported into the local namespace, then subpackage is imported into package's namespace and finally module is imported into package.subpackage's namespace. Imports using from ... import ... as ... perform the same sequence of operations, but the imported objects are bound directly to names in the importing module's namespace. The fact that the package name isn't bound in your local namespace does not mean it hasn't been imported (as inspection of sys.modules will show).

The __init__.py in a package serves much the same function as a module's .py file. A package, having structure, is written as a directory which can also contain modules (regular .py files) and subdirectories (also containing an __init__.py file) for any sub_packages. When the package is imported a new namespace is created and the package's __init__.py is executed with that namespace as the local and global namespaces. So to answer your problem we can strip your filestore down by omitting the top-level package, which will never be considered by the interpreter when test.py is run as a program. It would then look like this:

test.py
subpackage/
    __init__.py
    hello_world.py

Now, subpackage is no longer a sub-package, as we have removed the containing package as irrelevant. Focusing on why the do_something name is undefined might help. test.py does not contain any import, and so it's unclear how you are expecting do_something to acquire meaning. You could make it work by using an empty subpackage/__init__.py and then you would write test.py as

from subpackage.hello_world import do_something
do_something()

Alternatively you could use a subpackage/__init__.py that reads

from hello_world import do_something

which establishes the do_something function inside the subpackage namespace when the package is imported. Then use a test.py that imports the function from the package, like this:

from subpackage import do_something
do_something()

A final alternative with the same __init__.py is to use a test.py that simply imports the (sub)package and then use relative naming to access the required function:

import subpackage
subpackage.do_something()

to gain access to it in your local namespace.

With the empty __init__.py this could also be achieved with a test.py reading

import subpackage.hello_world
subpackage.hello_world.do_something()

or even

from subpackage.hello_world import do_something
do_something()

An empty __init__.py will mean that the top-level package namespace will contain only the names of any subpackages the program imports, which allows you to import only the subpackages you require. This gives you control over the namespace of the top-level package.

While it's perfectly possible to define classes and functions in the __init__.py , a more normal approach is to import things into that namespace from submodules so that importers can just import the top-level package to gain access to its contents with a single-level attribute reference, or even use from to import only the names you specifically want.

Ultimately the best tool to keep you straight is a clear understanding of how import works and what effect its various forms have on the importing namespace.

2 of 3
4

First, you have to understand how import alone work:

import test.submodule.do_something

Would try to load do_something from submodule itself loaded from test.

You want to load something from subpackage, so start with that:

import subpackage

Fine, subpackage/__init__.py is loaded.

Now, you want the do_something() function which is in the file (a "module") hello_world.py. Easy:

from subpackage.hello_world import do_something

And you are done! Just read this line loud, it does exactly what it says: import do_something from the module hello_world which is in the subpackage package.

Try that in test.py

from subpackage.hello_world import do_something

do_something()

It should work just fine.

Now, the second issue:

__init__.py won't be called in package/ since you don't use package/ as a package. __init__.py will be used if you do an import of package/ or anything in it, for eg:

from package import test

Otherwise, it won't be loaded at all.

However, if you want to load do_something() on the import of subpackage, put from submodule.hello_word import do_something in subpackage/__init__.py, and then, in you test.py, do a import subpackage.

🌐
Geo-python
geo-python.github.io › site › notebooks › L4 › modules.html
Loading and using modules — Geo-Python site documentation
Though this can be useful, it has the drawback that the imported function could conflict with other built-in or imported function names, and you lose the information about which module contains the function. You should only do this when you truly need to. Some modules have submodules that can also be imported without importing the entire module.
🌐
Python Forum
python-forum.io › thread-24716.html
submodule import problem
I am having a problem with modules and packages. I can make my imports work outside the package or I can make them work inside the package. I have not figured out a way to make them work in both scopes and I assume this is because I am still rather...
Find elsewhere
🌐
Python documentation
docs.python.org › 3 › reference › import.html
5. The import system — Python 3.15.2 documentation
Changed in version 3.10: Use of load_module() will raise ImportWarning. When a submodule is loaded using any mechanism (e.g. importlib APIs, the import or import-from statements, or built-in __import__()) a binding is placed in the parent module’s namespace to the submodule object.
🌐
GitHub
github.com › PyO3 › pyo3 › issues › 759
ModuleNotFoundError: No module named 'supermodule.submodule'; 'supermodule' is not a package · Issue #759 · PyO3/pyo3
February 8, 2020 - 🐛 Bug Reports I am working for writing Python extension, but facing import submodule error. ModuleNotFoundError: No module named 'supermodule.submodule'; 'supermodule' is not a pack...
Author: PyO3
Top answer
1 of 1
1

If the various modules form a single project, they should be part of a common package and use relative imports (from ..foo import specific_function). For example, instead of this project layout:

my-project/
  scripts/
    ...
  p_foo/
    __init__.py
  p_bar/
    __init__.py

I would expect a layout like this, without any Git submodules or similar:

my-project/
  p/
    __init__.py
    __main__.py
    foo/
      ...
    bar/
      ...

(The __main__.py file allows the module to be used as a command line tool like python3 -m MODULE OPTIONS....)

If these modules should be installed and developed separately as their own packages, they should instead all have a setup.py so that they are PIP-installable, and declare their dependencies on the other packages. It is OK if the dependency is not resolved via PyPI but e.g. through a Git URL. With setuptools, the setup.py can declare entrypoints. These entrypoints will be installed by PIP in a way that allows them to be invoked as ordinary command line tools. By installing in development/editable mode (pip -e), this will not impede your edit–test cycle.

Approaches like setting the PYTHONPATH technically work, but that is only really suitable for self-contained applications that don't have to interact with other packages. But you should not expect that your scripts will only be invoked for a certain working directory in order to resolve imports, so setting the PYTHONPATH (or sys.path) can have merit. In my opinion, the previously suggested mechanism – to let PIP sort out the paths – is vastly superior.

A note on Git submodules: they are great for including some other repo at a local path. This is a good alternative to “vendoring” dependencies, i.e. to literally copying the source code of the dependency. However, you have to explicitly select a commit that the submodule should use – it will not automatically follow the HEAD of a repository. Thus, submodules are most appropriate for referencing stable-ish internal repositories that will be updated occasionally, but are entirely unsuitable for closely related projects that will be developed together. If you expect to regularly have changes that will span multiple projects, that can indicate that you should keep all components in a single monorepo.

🌐
LambdaTest Community
community.lambdatest.com › general discussions
Which is the right way to use Python import for submodules? - LambdaTest Community
January 22, 2025 - What is the correct way to use Python import to import a name from a submodule? I’m trying to replicate the behavior of from foo.bar import object using the __import__ function, but I seem to be encountering issues. For simpler cases, like from glob import glob, it’s straightforward: glob = __import__("glob").glob However, the problem arises when I’m trying to import a name from a subpackage (e.g., from foo.bar import object).
🌐
Julienharbulot
julienharbulot.com › python-dynamical-import.html
How to dynamically import all classes in a python submodule
September 23, 2019 - Python code is organized in folders called packages containing .py files called modules. In this article, I show a trick to automatically import in the top-level package all the classes defined in the submodules. This shorten the import statements for the convenience of the end user.
🌐
Python
docs.python.org › 3 › c-api › import.html
Importing Modules — Python 3.15.2 documentation
The return value is a new reference to the imported module or top-level package, or NULL with an exception set on failure. Like for __import__(), the return value when a submodule of a package was requested is normally the top-level package, unless a non-empty fromlist was given.
🌐
Python.org
discuss.python.org › python help
Why do relative from-imports also add the submodule itself to the namespace? - Python Help - Discussions on Python.org
March 3, 2023 - Hi, Here is a common idiom found in many packages. For example in asyncio/__index__.py: # This relies on each of the submodules having an __all__ variable. from .base_events import * from .coroutines import * ... __a…
🌐
Curiousefficiency
python-notes.curiousefficiency.org › en › latest › python_concepts › import_traps.html
Traps for the Unwary in Python’s Import System - Alyssa Coghlan's Python Notes
This next trap exists in all current versions of Python, including 3.3, and can be summed up in the following general guideline: “Never add a package directory, or any directory inside a package, directly to the Python path”. The reason this is problematic is that every module in that directory is now potentially accessible under two different names: as a top level module (since the directory is on sys.path) and as a submodule of the package (if the higher level directory containing the package itself is also on sys.path).
🌐
IT trip
en.ittrip.xyz › python
The Essential Guide to Importing Submodules in Python: A Deep Dive | IT trip
November 4, 2023 - Python’s import system is built on the idea of modules, which are simply files containing Python definitions and statements. A submodule is a module that is a part of another module, and it can be a single file or a directory of scripts.
Top answer
1 of 1
116

How to use python's __import__() function properly?

There are two kinds of uses:

  • direct importing
  • a hook to alter import behavior

For the most part, you don't really need to do either.

For user-space importing

Best practice is to use importlib instead. But if you insist:

Trivial usage:

>>> sys = __import__('sys')
>>> sys
<module 'sys' (built-in)>

Complicated:

>>> os = __import__('os.path')
>>> os
<module 'os' from '/home/myuser/anaconda3/lib/python3.6/os.py'>
>>> os.path
<module 'posixpath' from '/home/myuser/anaconda3/lib/python3.6/posixpath.py'>

If you want the rightmost child module in the name, pass a nonempty list, e.g. [None], to fromlist:

>>> path = __import__('os.path', fromlist=[None])
>>> path
<module 'posixpath' from '/home/myuser/anaconda3/lib/python3.6/posixpath.py'>

Or, as the documentation declares, use importlib.import_module:

>>> importlib = __import__('importlib')
>>> futures = importlib.import_module('concurrent.futures')
>>> futures
<module 'concurrent.futures' from '/home/myuser/anaconda3/lib/python3.6/concurrent/futures/__init__.py'>

Documentation

The docs for __import__ are the most confusing of the builtin functions.

__import__(...)
    __import__(name, globals=None, locals=None, fromlist=(), level=0) -> module

    Import a module. Because this function is meant for use by the Python
    interpreter and not for general use it is better to use
    importlib.import_module() to programmatically import a module.

    The globals argument is only used to determine the context;
    they are not modified.  The locals argument is unused.  The fromlist
    should be a list of names to emulate ``from name import ...'', or an
    empty list to emulate ``import name''.
    When importing a module from a package, note that __import__('A.B', ...)
    returns package A when fromlist is empty, but its submodule B when
    fromlist is not empty.  Level is used to determine whether to perform 
    absolute or relative imports. 0 is absolute while a positive number
    is the number of parent directories to search relative to the current module.

If you read it carefully, you get the sense that the API was originally intended to allow for lazy-loading of functions from modules. However, this is not how CPython works, and I am unaware if any other implementations of Python have managed to do this.

Instead, CPython executes all of the code in the module's namespace on its first import, after which the module is cached in sys.modules.

__import__ can still be useful. But understanding what it does based on the documentation is rather hard.

Full Usage of __import__

To adapt the full functionality to demonstrate the current __import__ API, here is a wrapper function with a cleaner, better documented, API.

def importer(name, root_package=False, relative_globals=None, level=0):
    """ We only import modules, functions can be looked up on the module.
    Usage: 

    from foo.bar import baz
    >>> baz = importer('foo.bar.baz')

    import foo.bar.baz
    >>> foo = importer('foo.bar.baz', root_package=True)
    >>> foo.bar.baz

    from .. import baz (level = number of dots)
    >>> baz = importer('baz', relative_globals=globals(), level=2)
    """
    return __import__(name, locals=None, # locals has no use
                      globals=relative_globals, 
                      fromlist=[] if root_package else [None],
                      level=level)

To demonstrate, e.g. from a sister package to baz:

baz = importer('foo.bar.baz')    
foo = importer('foo.bar.baz', root_package=True)
baz2 = importer('bar.baz', relative_globals=globals(), level=2)

assert foo.bar.baz is baz is baz2

Dynamic access of names in the module

To dynamically access globals by name from the baz module, use getattr. For example:

for name in dir(baz):
    print(getattr(baz, name))

Hook to alter import behavior

You can use __import__ to alter or intercept importing behavior. In this case, let's just print the arguments it gets to demonstrate we're intercepting it:

old_import = __import__

def noisy_importer(name, locals, globals, fromlist, level):
    print(f'name: {name!r}')
    print(f'fromlist: {fromlist}')
    print(f'level: {level}')
    return old_import(name, locals, globals, fromlist, level)

import builtins
builtins.__import__ = noisy_importer

And now when you import you can see these important arguments.

>>> from os.path import join as opj
name: 'os.path'
fromlist: ('join',)
level: 0
>>> opj
<function join at 0x7fd08d882618>

Perhaps in this context getting the globals or locals could be useful, but no specific uses for this immediately come to mind.