Relative imports from __init__ in multi-file Django apps - python

I have a Django project located at /var/django/project/ where /var/django/ is in the PATH
within that project I have:
___init__.py
manage.py
utils/
__init__.py
tools.py
utils/__init__.py contains a function named get_preview
utils/tools.py contains a function named get_related
How can utils/__init__.py import get_related from utils/tools.py?
How can utils/tools.py import get_preview from utils/__init_.py?
I have tried relative imports as well as static imports but seem to get an error in tools.py when I try to from project.utils import get_preview

Yeah, this is bad structure. You gotta watch out here with creating a circular import between the two files.
About circular imports.

You can't (and shouldn't). You are structuring your code very poorly if files in your module are referencing code in the __init__.py associated with it. Either move both functions into __init__.py or both of them out of __init__.py or put them into separate modules. Those are your only options.

You can do it, you just need to make one of the imports happen at runtime to avoid the circular import.
For example, __init__.py:
from project.utils.tools import get_related
def get_preview():
# ...
and tools.py:
def get_related():
from project.utils import get_preview
# ...
get_preview()

Related

Python-Django: module import syntax conflicting

I hope this is not a duplicate, I couldn't find any other answer.
Going straight to the point, my problem is as follows.
I have a project in Django where django-apps use external custom modules.
This is the structure:
Project_dir/
- core/
- module_1.py
- module_2.py
- django_project/
- __init__.py
- settings.py
- urls.py
- wsgi.py
- django_app_A/
- views.py
- manage.py
The problem is that I need to import some classes and methods of moudule_2 in module_1, and I would do so by simply, in module_1,
from module_2 import foo
When I run module_1 for testing, everything works fine. Nonetheless, I need to import module_1 in django_app_A/views.py, and I would do so by
from core.module_1 import Bar
Here's the problem: if I have another relative import in module_1, as I have, I will get a
ModuleNotFoundError: No module named 'module_2'
UNLESS I use in module_1 the syntax
from .module_2 import foo
By doing so, the Django app will work fine and page will properly load, but at the same time I "break" the module_1, as I won't be able to run it stand-alone anymore, as I will get a
ModuleNotFoundError: No module named '__main__.module_2'
I have no idea how to fix this conflict and make both import syntax work at the same time.
Any clues? Am I missing something?
Thanks in advance
You should use absolute imports as much as you can.
from core.module_2 import foo
I can't be sure, but it sounds like a circular import problem to me.
Do you need the import to be on the "main" level? If you import module 2 inside of a class or function, simply write
def function_in_question():
import module_1
return module_1.whatever()
Another thing to look for: are you using it in a way that is actually circular? A function in module_2 using a function in module_1 that uses the function in module_2?

What is the most pythonic way to import 'sibling' modules into one another?

By 'sibling' modules, I mean two submodules that exist at the same depth within a parent module.
I'm trying to create a flask project using Flask-Restful, and it recommends structuring the project using this schema:
myapi/
__init__.py
app.py # this file contains your app and routes
resources/
__init__.py
foo.py # contains logic for /Foo
bar.py # contains logic for /Bar
common/
__init__.py
util.py # just some common infrastructure
I really like this structure, but I'm not sure how to import something from the 'common' module into the 'resources' module. Can anyone help me out?
In common/__init__.py
from myapi.common.utils import A, B
In resource/foo.py
from myapi.common import A
You can also relative imports in __init__.py like from .utils import A.

Importing classes defined in the same module

I am having trouble using my classes that I've defined in a module. I've looked at this stackoverlfow post, and the answer seems to be "you don't need imports." This is definitely not the behavior I'm experiencing. I'm using Python 3.3. Here is my directory structure:
root/
__init__.py
mlp/
__init__.py
mlp.py
layers/
__init__.py
hidden_layer.py
dropout_layer.py
My problem is this: the class defined in dropout_layer.py extends the class in hidden_layer.py, but when I try to import hidden_layer, I sometimes get an error depending on the directory I execute my code from. For instance, from layers.hidden_layer import HiddenLayer then I run my code if I execute it from root/mlp. This import does not work, however, if I execute my code from root. This is strange behavior to me. How can I get this working correctly?
My only non-empty __init__.py file is in root/mlp/layers/:
# root/mlp/layers/__init__.py
__all__ = ['hidden_layer', 'dropout_layer']
In Python 3 you can prepend a . for an import relative to the location of the current module:
from .hidden_layer import HiddenLayer

Lazy loading module imports in an __init__.py file python

I was wondering if anyone had any suggestions for lazy loading imports in an init file? I currently have the following folder structure:
/mypackage
__init__.py
/core
__init__.py
mymodule.py
mymodule2.py
The init.py file in the core folder with the following imports:
from mymodule import MyModule
from mymodule2 import MyModule2
This way I can just do:
from mypackage.core import MyModule, MyModule2
However, in the package init.py file, I have another import:
from core.exc import MyModuleException
This has the effect that whenever I import my package in python, MyModule and MyModule2 get imported by default because the core init.py file has already been run.
What I want to do, is only import these modules when the following code is run and not before:
from mypackage.core import MyModule, MyModule2
Any ideas?
Many thanks.
Unless I'm mistaking your intentions, this is actually possible but requires some magic.
Basically, subclass types.ModuleType and override __getattr__ to import on demand.
Check out the Werkzeug init.py for an example.
You can't. Remember that when python imports it executes the code in the module. The module itself doesn't know how it is imported hence it cannot know whether it has to import MyModule(2) or not.
You have to choose: allow from mypackage.core import A, B and from core.exc import E does the non-needed imports (x)or do not import A and B in core/__init__.py, hence not allowing from mypackage.core import A, B.
Note: Personally I would not import MyModule(2) in core/__init__.py, but I'd add an all.py module that does this, so the user can do from mypackage.core.all import A, B
and still have from mypackage.core.exc import TheException not loading the unnecessary classes.
(Actually: the all module could even modify mypackage.core and add the classes to it, so that following imports of the kind from mypackage.core import MyModule, MyModule2 work, but I think this would be quite obscure and should be avoided).
If your modules structure is like:
/mypackage
__init__.py
/core
__init__.py
MyModule.py
MyModule2.py
or:
/mypackage
__init__.py
/core
__init__.py
/MyModule
__init__.py
/MyModule2
__init__.py
then feel free to use
from mypackage.core import MyModule, MyModule2
without importing them in __init__.py under mypackage/core
Not sure if it applies here but in general lazy loading of modules can be done using the Importing package.
Works like this:
from peak.util.imports import lazyModule
my_module = lazyModule('my_module')
Now my module is only really imported when you use it the first time.
You may use follow code in __init__ in module:
import apipkg
apipkg.initpkg(__name__, {
'org': {
'Class1': "secure._mypkg:Class1",
'Class2': "secure._mypkg2:Class2",
}
})
I realize that this question was posted a very long time ago and since then there has been some helpful updates to solve lazy loading submodules. So for anyone else looking for how to solve this we have great options available now.
Specifically PEP 562
Here is an excerpt from that article:
Another widespread use case for getattr would be lazy submodule imports. > Consider a simple example:
# lib/__init__.py
import importlib
__all__ = ['submod', ...]
def __getattr__(name):
if name in __all__:
return importlib.import_module("." + name, __name__)
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
# lib/submod.py
print("Submodule loaded")
class HeavyClass:
...
# main.py
import lib
lib.submod.HeavyClass # prints "Submodule loaded"

Python: Unit Testing Module and Relative Imports

Currently have the following file hierarchy:
\package
__init__.py
run_everything.py
\subpackage
__init__.py
work.py
work1.py
work2.py
\test
__init__.py
test_work.py
test_work1.py
My first question is regarding relative imports. Suppose in \subpackage\work.py I have a function called custom_function(), and I would like to test that function in test_work.py. For some reason I can not figure out how to make this import from one module to another. Trying from .. subpackage.work1 import custom_function() does not seem to work, and yields the error Attempted relative import in non-package Is there any way to resolve this?
2)
I would like to run all test files from run_everything.py with one function, would adding a suite() function in each test_work*.py file, which adds each unit_testing class to suite.addTest(unittest.makeSuite(TestClass)), and finally importing them into the top-level run_everything.py be the most conventional way in Python2.7?
Here is a hack*
Insert the path's to "subpackage" and "test" to your python path in run_everything using:
import sys
sys.path.insert(0, '/path/to/package/subpackage')
sys.path.insert(0, '/path/to/package/test')
And then, you can import all your files using vanilla imports in run_everything:
import work, work1, work2
import test_work, test_work1
*This won't permanently affect your PYTHONPATH.

Categories

Resources