Cyclic "import xyz as abc" - python

I have a problem when I try to have a cyclic import in Python 3. I am writing a PyQt4 app and I want to make some object available in the whole app. This way I end up having some files:
index.py
import source.blab as bl
source/blab.py
import source.windows
windows = source.windows.Windows()
source/windows.py
import source.window_clients.main_window
class Windows:
...
source/window_clients/main_window.py
import source.blab
class MainWindow(QWidget):
...
So far, the code works. However, for aesthetic reasons, I would like to change the import command in main_window.py into:
import source.blab as bl
which throws an:
AttributeError: module 'source' has no attribute 'blab'
I am sure, this is related to Circular (or cyclic) imports in Python where they say that one cannot use from a * import b in a cyclic import. Is it the same for import a as b? If so, is there another way to change the name of the imported module?

It seems that this is a known bug that has been fixed now.
The reasons have to do with how the import statement was implemented in the different cases.

Related

how do i correctly import a package in python?

Hello everyone im currently learning python and i im having some problems importing modules and packages. Actually i think is more of a problem with vscode.
i have this package called "paquete" with a module (funciones) that i want to import to my "main" with some fuctions in it to test if it all works correctly but i still getting "emphasized items and unresolved-import" warnings.
but for some reason it works just fine.
is more of a annoying thing.
EDIT:
module with the function "funcion"
the warning that appears in the main folder "prueba" is "emphasized items"
i tried what u guys told me to do but it stills shows the warnings
As you are trying to import a specific function from module in python
You should use in this manner:
from paquete import funciones
If you want to import full module then use:
import paquete
I can't tell whats in the funciones file. But normally this yellow import lines are telling you that you import functions, which you dont use.
Try this instead if you only want
funcion
to be imported.
from paquete.funcions import funcion
This is also better because you import only the functions you need, not all of the functions you declared in the other file. Also all imports of the other file will be loaded into your file if you import with an asterix.
The issue is you are doing all of this from within a directory named prueba. If you changed the import to from prueba.paquete.funciones import * it should work after you add a __init__.py file to your prueba directory. The other option is to use a relative import: from .paquete.funciones import *.
But do note that using import * is strongly discouraged when you are not working within the REPL. It's much better to import to the module and then reference things off the module, e.g. from prueba.paquete import funciones, from .paquete import funciones, or import prueba.paquete.funciones. That way you know exactly where things in your code came from without having to read the top of your file.
pip3 intall "name"
Use Pycharm, rather than Vscode

Importing identically named methods

So I have two separate Python packages that I'm importing into my Python script for Raspberry Pi. In this case as;
from rflib import*
from Rpi.GPIO import*
However, both packages have their own seperate method cleanup(self)
So, at the end of the script when I use the command
cleanup(), how do I a) know which package the method is coming from (they both do utterly different things b) control which one is run?
I've looked into similarly named questions, but which seem to deal with inheritance overloading rather than package imports
from <module> import * takes all names in a module (those that don't start with a _ or everything listed in <module>.__all__ and assigns those names as globals in your current module.
If two modules define the same name, that means that the last one imported this way wins; cleanup = rflib.cleanup is replaced by cleanup = Rpi.GPIO.cleanup with the second from Rpi.GPIO import * statement.
You generally want to avoid using from <module> import *. Import specific names, or just the module itself.
In this case, you can do:
from rflib import cleanup as rflib_cleanup
from Rpi.GPIO import cleanup as rpigpio_cleanup
which would bind those two functions as different names.
Or you could just import the modules:
import rflib
from Rpi import GPIO
which gives you only the rflib and GPIO names, each a reference to the module object, so now you can reference each of the cleanup functions as attributes on those modules:
rflib.cleanup()
GPIO.cleanup()
If you need to use a lot of names from either module, the latter style is preferred because that limits the number of imports you need to do, keeps your namespace clean and un-cluttered, and gives you more context whereever those names are used in your code.
It is not a good practice to use * with import. You should be doing something like:
import rflib
from Rpi import GPIO
# Clean Up 1
rflib.cleanup
#Clean Up 2
GPIO.cleanup()
Additional pice of information:
In case your files/objects are of same name, in that case you should use as with import. For example:
from file1 import utils as file1_utils
from file2 import utils as file2_utils
file1_utils.my_func()
file2_utils.my_func()

cannot import function python structure [duplicate]

I have some code spread across multiple files that try to import from each other, as follows:
main.py:
from entity import Ent
entity.py:
from physics import Physics
class Ent:
...
physics.py:
from entity import Ent
class Physics:
...
I then run from main.py and I get the following error:
Traceback (most recent call last):
File "main.py", line 2, in <module>
from entity import Ent
File ".../entity.py", line 5, in <module>
from physics import Physics
File ".../physics.py", line 2, in <module>
from entity import Ent
ImportError: cannot import name Ent
I'm assume the error is due to importing entity twice - once in main.py and later in physics.py - but how can I work around the problem?
See also What happens when using mutual or circular (cyclic) imports in Python? for a general overview of what is allowed and what causes a problem WRT circular imports. See Why do circular imports seemingly work further up in the call stack but then raise an ImportError further down? for technical details on why and how the problem occurs.
You have circular dependent imports. physics.py is imported from entity before class Ent is defined and physics tries to import entity that is already initializing. Remove the dependency to physics from entity module.
While you should definitely avoid circular dependencies, you can defer imports in python.
for example:
import SomeModule
def someFunction(arg):
from some.dependency import DependentClass
this ( at least in some instances ) will circumvent the error.
This is a circular dependency. It can be solved without any structural modifications to the code. The problem occurs because in vector you demand that entity be made available for use immediately, and vice versa. The reason for this problem is that you asking to access the contents of the module before it is ready -- by using from x import y. This is essentially the same as
import x
y = x.y
del x
Python is able to detect circular dependencies and prevent the infinite loop of imports. Essentially all that happens is that an empty placeholder is created for the module (ie. it has no content). Once the circularly dependent modules are compiled it updates the imported module. This is works something like this.
a = module() # import a
# rest of module
a.update_contents(real_a)
For python to be able to work with circular dependencies you must use import x style only.
import x
class cls:
def __init__(self):
self.y = x.y
Since you are no longer referring to the contents of the module at the top level, python can compile the module without actually having to access the contents of the circular dependency. By top level I mean lines that will be executed during compilation as opposed to the contents of functions (eg. y = x.y). Static or class variables accessing the module contents will also cause problems.
In my case, I was working in a Jupyter notebook and this was happening due the import already being cached from when I had defined the class/function inside my working file.
I restarted my Jupyter kernel and the error disappeared.
To make logic clear is very important. This problem appear, because the reference become a dead loop.
If you don't want to change the logic, you can put the some import statement which caused ImportError to the other position of file, for example the end.
a.py
from test.b import b2
def a1():
print('a1')
b2()
b.py
from test.a import a1
def b1():
print('b1')
a1()
def b2():
print('b2')
if __name__ == '__main__':
b1()
You will get Import Error: ImportError: cannot import name 'a1'
But if we change the position of from test.b import b2 in A like below:
a.py
def a1():
print('a1')
b2()
from test.b import b2
And the we can get what we want:
b1
a1
b2
This is a circular dependency.
we can solve this problem by using import module or class or function where we needed.
if we use this approach, we can fix circular dependency
A.py
from B import b2
def a1():
print('a1')
b2()
B.py
def b1():
from A import a1
print('b1')
a1()
def b2():
print('b2')
if __name__ == '__main__':
b1()
I just got this error too, for a different reason...
from my_sub_module import my_function
The main script had Windows line endings. my_sub_module had UNIX line endings. Changing them to be the same fixed the problem. They also need to have the same character encoding.
As already mentioned, this is caused by a circular dependency. What has not been mentioned is that when you're using Python typing module and you import a class only to be used to annotate Types, you can use Forward references:
When a type hint contains names that have not been defined yet, that
definition may be expressed as a string literal, to be resolved later.
and remove the dependency (the import), e.g. instead of
from my_module import Tree
def func(arg: Tree):
# code
do:
def func(arg: 'Tree'):
# code
(note the removed import statement)
The problem is clear: circular dependency between names in entity and physics modules.
Regardless of importing the whole module or just a class, the names must be loaded .
Watch this example:
# a.py
import b
def foo():
pass
b.bar()
# b.py
import a
def bar():
pass
a.foo()
This will be compiled into:
# a.py
# import b
# b.py
# import a # ignored, already importing
def bar():
pass
a.foo()
# name a.foo is not defined!!!
# import b done!
def foo():
pass
b.bar()
# done!
With one slight change we can solve this:
# a.py
def foo():
pass
import b
b.bar()
# b.py
def bar():
pass
import a
a.foo()
This will be compiled into:
# a.py
def foo():
pass
# import b
# b.py
def bar():
pass
# import a # ignored, already importing
a.foo()
# import b done!
b.bar()
# done!
Try this solution: rename your working python script
You should not name your current python script with the name of some other module you import, since you will get that error.
Example:
you are working in medicaltorch.py
in that script, you have: from medicaltorch import X where medicaltorch is supposed to be a separate installed module
This will fail with the ImportError since 2 things refer to medicaltorch
So, just rename your working python script in 1.
If you are importing file1.py from file2.py and used this:
if __name__ == '__main__':
# etc
Variables below that in file1.py cannot be imported to file2.py because __name__ does not equal __main__!
If you want to import something from file1.py to file2.py, you need to use this in file1.py:
if __name__ == 'file1':
# etc
In case of doubt, make an assert statement to determine if __name__=='__main__'
Don't see this one here yet - this is incredibly stupid, but make sure you're importing the correct variable/function.
I was getting this error
ImportError: cannot import name IMPLICIT_WAIT
because my variable was actually IMPLICIT_TIMEOUT.
when I changed my import to use the correct name, I no longer got the error 🤦‍♂️
One way to track import error is step by step trying to run python on each of imported files to track down bad one.
you get something like:
python ./main.py
ImportError: cannot import name A
then you launch:
python ./modules/a.py
ImportError: cannot import name B
then you launch:
python ./modules/b.py
ImportError: cannot import name C (some NON-Existing module or some other error)
Also not directly relevant to the OP, but failing to restart a PyCharm Python console, after adding a new object to a module, is also a great way to get a very confusing ImportError: Cannot import name ...
The confusing part is that PyCharm will autocomplete the import in the console, but the import then fails.
Not specifically for this asker, but this same error will show if the class name in your import doesn't match the definition in the file you're importing from.
In my case, simply missed filename:
from A.B.C import func_a (x)
from A.B.C.D import func_a (O)
where D is file.
I met this error too, but my case is less common, and it does throw this error too.
My case is that I encounter this error in jupyter notebook; I write from M import c where M is a python file and c is a class in M.py, the reason for the error is because c is just created a few minutes ago, but my jupyter notebook has been running for a long time, so I just need to restart the jupyter notebook and let it reload M.py.

How to import python class file from same directory?

I have a directory in my Python 3.3 project called /models.
from my main.py I simply do a
from models import *
in my __init__.py:
__all__ = ["Engine","EngineModule","Finding","Mapping","Rule","RuleSet"]
from models.engine import Engine,EngineModule
from models.finding import Finding
from models.mapping import Mapping
from models.rule import Rule
from models.ruleset import RuleSet
This works great from my application.
I have a model that depends on another model, such that in my engine.py I need to import finding.py in engine.py. When I do: from finding import Finding
I get the error No Such Module exists.
How can I import class B from file A in the same module/directory?
Since you are using Python 3, which disallows these relative imports (it can lead to confusion between modules of the same name in different packages).
Use either:
from models import finding
or
import models.finding
or, probably best:
from . import finding # The . means "from the same directory as this module"
Apparently I can do: from .finding import Finding and this works.
And the answer below reflects this as well so I guess this is reasonably correct.
I've fixed up my file naming and moved my tests to a different directory and I am running smoothly now. Thanks!

Creating a python library: how to write __init__.py

I have written a small Python library, currently hosted at BitBucket. As you can see, the library is called pygpstools, and it's made from 5 files:
gpstime.py → A class
satellite.py → A class
geodesy.py → A module with some geodesy methods
almanacs.py → A module with some almanac methods
constants.py → Some constants
I want to use it as written at the README. For example:
from pygpstools import GPSTime
GPSTime(wn=1751, tow=314880)
or:
import pygpstools
pygpstools.GPSTime(wn=1751, tow=314880)
But after installing my library with command python setup.py install I'm getting ImportError when trying to access GPSTime class like this.
I guess the problem is at the __init__.py file. When I asked about this at the python IRC channel, I was told that leaving it empty does the trick. But I have researched and it looks like that only tells Python that it is a module, but it is not enough to allow this kind of importing I'm looking for, as at any other library out there.
So I have tried (not currently updated at bitbucket) to use this as __init__.py:
__title__ = 'pygpstools'
__version__ = '0.1.1'
__author__ = 'Roman Rodriguez'
__license__ = 'MIT'
__copyright__ = 'Copyright 2013 Roman Rodriguez'
import almanacs
import constants
import geodesy
import gpstime
import satellite
but still doesn't work: ImportError for GPSTime.
What am I missing?
GPSTime, for example, is in the module gpstime, so its actual (relative) name is gpstime.GPSTime. So when you import gpstime in your __init__ you are actually making available the name gpstime which holds a reference to your type as gpstime.GPSTime.
So you would have to use from pygpstools import gpstime and then gpstime.GPSTime as the type name.
Obviously this is not what you want, so instead, you want to “collect” all your types in the __init__ module. You can do that by just making them available directly:
from almanacs import *
from constants import *
from geodesy import *
from gpstime import GPSTime
from satellite import *
I have used * now to import anything because I didn’t take a closer look at what actual types there are in your files. You should specify it though. It is also recommended, to define an __all__ list in your __init__ so that you can control which names are imported when writing from pygpstools import *.

Categories