Can't import classes from local files in Python - python

Python local import from files stored in at the same level of directory is often confusing to me. I have the following directory structure,
/distrib
__init__.py # empty
bases.py # contains classes MainBase etc.
extension.py # contains classes MainExtension etc
/errors
__init__.py
base_error.py
In file bases.py importing classes from extension.py is successful. For example, simply using from .extensions import MainExtension would work. On the other hand, in extensions.py, importing a class from bases.py faces challenges.
Attempt 1
If I from bases import MainBase, it complains ModuleNotFoundError: No module named 'bases'.
Attempt 2
If I specify it as local import by from .bases import MainBase, it complains ImportError: cannot import name 'MainBase'.
Attempt 3
If I import it using from . import bases, there is no error. But, consequently using bases.MainBase triggers error module distrib.bases has no attribute 'MainBase' and
it seem that all classes defined in the bases.py file are 'missing'.
However, in a different folder such as errors, I can import classes from distrib.bases normally. What exactly is happening here? Doesn't Python allow cyclical import?

You have a circular import. In your base module you try to import from extension. But from extension you import base. But base is not finished importing yet so that results in an ImportError when you try to import anything from the extensions module.

Related

Form A import B and import A causes troubles

I have a following problem. I have this folder structure:
folder
├──script.py
├──utils.py
└──venv
I would like to import functions from utils.py into script.py. When I try this from utils import function_a, function_b everything works. But when I try import utils I got an error NameError: name 'function_a' is not defined.
Whats the difference between from utils import function_a, function_b and import utils in this case? And how can I fix it, please?
import module : Nice when you are using many bits from the module. Drawback is that you'll need to qualify each reference with the module name.
from module import ... : Nice that imported items are usable directly without module name prefix. The drawback is that you must list each thing you use, and that it's not clear in code where something came from.
If you are importing the module itself, then you have to specify what you want to use from the module with the . operator:
import utils
utils.function_a()
utils.function_b()

Python circular import in custom package and __init__.py

I get ImportError: cannot import name 'Result' from partially initialized module 'libs.elastic_search_hunt' (most likely due to a circular import) error when I try to run tests.
But I does not see any circular imports in my code.
I have a package, named elastic_search_hunt which contains 3 modules:
elastic_query.py
elastic_query_result.py
search_processor.py
And I also have __init__.py file with following text:
from libs.elastic_search_hunt.elastic_query import Query
from libs.elastic_search_hunt.search_processor import SearchProcessor
from libs.elastic_search_hunt.elastic_query_result import Result
__all__ = ['Query', 'SearchProcessor', 'Result'] # I guess it does not have any effect
elastic_query.py has only external imports.
elastic_query_result.py the same.
search_processor.py has those import:
from . import Query
from . import Result
Then I have a test file, which imports Query class:
from libs.elastic_search_hunt import Query
When I run tests, I get this errors:
test_query.py:2: in <module>
from libs.elastic_search_hunt import Query
..\src\libs\elastic_search_hunt\__init__.py:2: in <module>
from libs.elastic_search_hunt.search_processor import SearchProcessor
..\src\libs\elastic_search_hunt\search_processor.py:4: in <module>
from . import Result
E ImportError: cannot import name 'Result' from partially initialized module 'libs.elastic_search_hunt' (most likely due to a circular import)
But where is any circular import in my code?
I only can assume that when I import Query from tests, it also import search_processor from the __init__.py module which in turn loads Query one more time. But the error is about Result in elastic_query_result module and I see only one import of Result.
When i delete search_processor from __init__.py everything works fine.
I have read a lot of issues about circular imports, but all of them was quite obvious and does not touch the __init__.py. What am I missing?
TL;DR: replace from . import Query with from .elastic_query import Query
Explanation:
When you import something from libs.elastic_search_hunt module it loads __init__.py at first. Since every module executes at first import __init__.py also being executed.
Then Python executes code from __init__.py and at second line
from libs.elastic_search_hunt.search_processor import SearchProcessor
it imports search_processor.py. Since it's first import - file must be executed - therefore all your imports in that file must be executed right now as well:
As you mentioned you have the following imports in your file:
from . import Query
from . import Result
At this point you tell python to load libs.elastic_search_hunt entire module and take Query, Result from it. So Python does.
It makes an attempt to load libs/elastic_search_hunt/__init__.py but wait... it is still not loaded completely. So it must load it, but in order to load it properly it must firstly load search_processor which requires elastic_search_hunt/__init__.py to be loaded.... oh well, there's a loop.
So in order to avoid such behaviour you should explicitly say from which module exactly you wish to load Query and Result, therefore change
from . import Query
from . import Result
to
from .elastic_query import Query
from .elastic_query_result import Result
Example: Failed
Example: Success

ModuleNotFound Error with VSCode Python 3.8.2

I'm a greenhorn, so go easy on me:
I've been trying to divide up a python project I was working on into smaller parts. To that end I created 4 Classes inside a single folder in VSCode, one being a main class that imports the other 3 and accesses their methods etc.
The structure is as following:
top_level_folder
|--lower_level_folder
|--class1.py
|--class2.py
|--class3.py
|--mainclass.py
Now my mainclass is supposed to import the other 3 classes, via
from top_level_folder.lower_level_folder import class1
etc.
However, doing it this way, I get a ModuleNotFound Error (no module named top_level_folder)
import class1
etc
results in a TypeError
and
import top_level_folder.lower_level_folder.class1 as x
doesn't work either
Is there something obvious I'm missing? Is it down to my VSC installation?
It depends. If you're running mainclass.py as your executable script, your import should look like this
mainclass.py
from class1 import MyClass
But if you're planning on importing the module from outside the folder, you'll either need an __init__.py file, or you would specify the folder name. I.e your file structure looks like this
top_level_folder
|--lower_level_folder
|--__init__.py
|--class1.py
|--class2.py
|--class3.py
|--mainclass.py
|--main.py
your would import like this
main.py
from mainclass import MyClass
mainclass.py
from lower_level_folder.class1 import MyClass2
__init__.py
from lower_level_folder.mainclass import MyClass

How to import an entire module from within the same directory

Sorry if this is a duplicate, but I couldn't find anything for this specific topic. So here's the question:
In python 3 when you want to import an object from some module you would write something like
from module import object
If you want to specify that the module is in the same diretory as the file you're currently working on, you'd precede the module name with a dot like
from .module import object
What do I have to write in order to import an entire module from within the same directory? Intuitively, I tried
import .module
But this gives me a syntax error.
The correct way is to import the module from the current package, i.e. ..
from . import module
This makes the module available with the name module.

gRPC generated python script fails to find a local module in the same directory? [duplicate]

In python 2 I can create a module like this:
parent
->module
->__init__.py (init calls 'from file import ClassName')
file.py
->class ClassName(obj)
And this works. In python 3 I can do the same thing from the command interpreter and it works (edit: This worked because I was in the same directory running the interpreter). However if I create __ init __.py and do the same thing like this:
"""__init__.py"""
from file import ClassName
"""file.py"""
class ClassName(object): ...etc etc
I get ImportError: cannot import name 'ClassName', it doesn't see 'file' at all. It will do this as soon as I import the module even though I can import everything by referencing it directly (which I don't want to do as it's completely inconsistent with the rest of our codebase). What gives?
In python 3 all imports are absolute unless a relative path is given to perform the import from. You will either need to use an absolute or relative import.
Absolute import:
from parent.file import ClassName
Relative import:
from . file import ClassName
# look for the module file in same directory as the current module
Try import it this way:
from .file import ClassName
See here more info on "Guido's decision" on imports in python 3 and complete example on how to import in python 3.

Categories