0

Let's say I have a module object foo and I want to dynamically add module bar to it at import time. How can I accomplish that?

Work done so far:

I've been trying to accomplish this by adding bar to the __init__.py file for foo.

bar = function_that_returns_module_bar()

This allows me to do

from foo import bar

However the following fails

import foo.bar

Furthermore, let's say bar has a submodule baz, I'm also unable to do

from foo.bar import baz

Is what I'm describing possible?

wallyk
  • 56,922
  • 16
  • 83
  • 148
mdornfe1
  • 1,982
  • 1
  • 24
  • 42
  • The is in fact what the `os` module does, which enables you to use the "sub-module" `os.path` after only importing `os`. – Amitai Irron May 14 '20 at 21:14
  • It's also a bad idea, and nothing else in the standard library has done the same thing since `os.path`, even when functionality is os-dependent. – user2357112 May 14 '20 at 21:29
  • Especially with submodules, doing this can lead to ["evil twin" classes](https://stackoverflow.com/questions/46715586/isinstance-unexpectedly-returning-false) and other nastiness. – user2357112 May 14 '20 at 21:31

1 Answers1

1

You can import the modules inside __init__.py

foo/__init__.py:

from foo import bar

foo/bar/__init__.py:

from foo.bar import baz

foo/bar/baz/__init__.py:

def g():
    return "Hello"

Then you can use the modules as follows:

from foo.bar import baz

baz.g()

EDIT:

If you don't really have the directories in your filesystem, then you have to manually add the modules to sys.modules dictionary (since when you just declare a variable on a module it is not added to sys.modules dictionary):

import sys

sys.modules['foo.bar'] = function_that_returns_bar_module()
jerry
  • 499
  • 4
  • 10
  • Is it possible to do this without import statements? I have a function that returns the module object. I’m not actually capable of doing this via imports. Since I have to work with the module returned by the function. – mdornfe1 May 14 '20 at 22:38
  • I've added such a scenario. – jerry May 15 '20 at 10:13