Namespaces with Module Imports - python

I am learning Python and am still a beginner, although I have been studying it for about a year now. I am trying to write a module of functions which is called within a main module. Each of the functions in the called module needs the math module to run. I am wondering if there is a way to do this without importing the math module inside the called module. Here is what I have:
main.py:
from math import *
import module1
def wow():
print pi
wow()
module1.cool()
module1.py:
def cool():
print pi
When running main.py I get:
3.14159265359
Traceback (most recent call last):
File "Z:\Python\main.py", line 10, in <module>
module1.cool()
File "Z:\Python\module1.py", line 3, in cool
print pi
NameError: global name 'pi' is not defined
What I'm having a hard time understanding is why I get a name error when running main.py. I know that the variable pi becomes global to the main module upon import because wow can access it. I also know that cool becomes global to the main module upon import because I can print module1.cool and get <function cool at 0x02B11AF0>. So since cool is inside the global namespace of the main module, shouldn't the program first look inside the function cool for the variable pi, and then when it doesn't find it there, look inside main module for the variable pi and find it there?
The only way to get around this that I know of is to import the math module inside module1.py. I don't like the idea of that, though because it makes things more complicated and I am a fan of nice, simple code. I feel like I am close to grasping namespaces, but need help on this one. Thanks.

As the traceback shows, the problem isn't in main.py, but in module1.py:
Traceback (most recent call last):
File "Z:\Python\main.py", line 10, in <module>
module1.cool()
File "Z:\Python\module1.py", line 3, in cool
print pi
NameError: global name 'pi' is not defined
In other words, in module1, there is no global name pi, because you haven't imported it there. When you do from math import * in main.py, that just imports everything from the math module's namespace into the main module's namespace, not into every module's namespace.
I think the key thing you're missing here is that each module has its own "global" namespace. This can be a bit confusing at first, because in languages like C, there's a single global namespace shared by all extern variables and functions. But once you get past that assumption, the Python way makes perfect sense.
So, if you want to use pi from module1, you have to do the from math import * in module1.py. (Or you could find some other way to inject it—for example, module1.py could do from main import *, or main.py could do module1.pi = pi, etc. Or you could cram pi into the magic builtins/__builtin__ module, or use various other tricks. But the obvious solution is to do the import where you want it imported.)
As a side note, you usually don't want to do from foo import * anywhere except the interactive interpreter or, occasionally, the top-level script. There are exceptions (e.g., a few modules are explicitly designed to be used that way), but the rule of thumb is to either import foo or use a limited from foo import bar, baz.

"Explicit is better than implicit" is a design decision that was made by the creators of Python (launch python and run import this).
Therefore, when you run module1.cool(), Python will not look for the undefined pi in the main module.
You'll have to import the math module in explicitly whenever you want to use it - that's just how Python works.
Also, you should avoid from X import *-style imports, that's bad practice too. Here, you could do: from math import pi.

As others have said, there isn't actually a global pi in your module1. A good solution for you is this, which only imports pi once from math and explicitly ensures that the pi you're getting is the one from module1:
main.py:
import module1
def wow():
print module1.pi
wow()
module1.cool()
module1.py:
from math import pi
def cool():
print pi

The simple approach of exec (python 3) or execfile (python 2) as mentioned in the comments by #abarnert may be useful for some workflows. All that is needed is to replace the import line with:
exec( open("module1.py").read() ) # python 3
and then you can simply call the function with cool() rather than module1.cool(). Within cool(), the variable pi will behave like a global, as the OP had originally expected.
In a nutshell, this is simply hiding a function definition that would otherwise appear at the top of your main program and has both advantages and disadvantages. For large projects with multiple modules and imports, using exec (instead of a proper namespaces) is probably a mistake as you don't generally want to keep too many things within a single global namespace.
But for simple cases (like using Python as a shell script) exec gives you a simple and concise way to hide shared functions while letting them share the global namespace. Just note that in this case you might want to give extra thought to how you name your functions (e.g. use v1_cool and v2_cool to keep track of different versions since you can't do v1.cool and v2.cool).
One less obvious disadvantage of using exec here is that errors in the executed code may not display the line number of the error although you can work around this: how to get the line number of an error from exec or execfile in Python

Inside the module you could simply define from math import pi, which would only import pi from math but not the entire math module.

Related

Custom typing in Python [duplicate]

I'm getting this error
Traceback (most recent call last):
File "/Users/alex/dev/runswift/utils/sim2014/simulator.py", line 3, in <module>
from world import World
File "/Users/alex/dev/runswift/utils/sim2014/world.py", line 2, in <module>
from entities.field import Field
File "/Users/alex/dev/runswift/utils/sim2014/entities/field.py", line 2, in <module>
from entities.goal import Goal
File "/Users/alex/dev/runswift/utils/sim2014/entities/goal.py", line 2, in <module>
from entities.post import Post
File "/Users/alex/dev/runswift/utils/sim2014/entities/post.py", line 4, in <module>
from physics import PostBody
File "/Users/alex/dev/runswift/utils/sim2014/physics.py", line 21, in <module>
from entities.post import Post
ImportError: cannot import name Post
and you can see that I use the same import statement further up and it works. Is there some unwritten rule about circular importing? How do I use the same class further down the call stack?
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 What can I do about "ImportError: Cannot import name X" or "AttributeError: ... (most likely due to a circular import)"? for techniques for resolving and avoiding circular dependencies.
I think the answer by jpmc26, while by no means wrong, comes down too heavily on circular imports. They can work just fine, if you set them up correctly.
The easiest way to do so is to use import my_module syntax, rather than from my_module import some_object. The former will almost always work, even if my_module included imports us back. The latter only works if my_object is already defined in my_module, which in a circular import may not be the case.
To be specific to your case: Try changing entities/post.py to do import physics and then refer to physics.PostBody rather than just PostBody directly. Similarly, change physics.py to do import entities.post and then use entities.post.Post rather than just Post.
When you import a module (or a member of it) for the first time, the code inside the module is executed sequentially like any other code; e.g., it is not treated any differently that the body of a function. An import is just a command like any other (assignment, a function call, def, class). Assuming your imports occur at the top of the script, then here's what's happening:
When you try to import World from world, the world script gets executed.
The world script imports Field, which causes the entities.field script to get executed.
This process continues until you reach the entities.post script because you tried to import Post
The entities.post script causes physics module to be executed because it tries to import PostBody
Finally, physics tries to import Post from entities.post
I'm not sure whether the entities.post module exists in memory yet, but it really doesn't matter. Either the module is not in memory, or the module doesn't yet have a Post member because it hasn't finished executing to define Post
Either way, an error occurs because Post is not there to be imported
So no, it's not "working further up in the call stack". This is a stack trace of where the error occurred, which means it errored out trying to import Post in that class. You shouldn't use circular imports. At best, it has negligible benefit (typically, no benefit), and it causes problems like this. It burdens any developer maintaining it, forcing them to walk on egg shells to avoid breaking it. Refactor your module organization.
To understand circular dependencies, you need to remember that Python is essentially a scripting language. Execution of statements outside methods occurs at compile time. Import statements are executed just like method calls, and to understand them you should think about them like method calls.
When you do an import, what happens depends on whether the file you are importing already exists in the module table. If it does, Python uses whatever is currently in the symbol table. If not, Python begins reading the module file, compiling/executing/importing whatever it finds there. Symbols referenced at compile time are found or not, depending on whether they have been seen, or are yet to be seen by the compiler.
Imagine you have two source files:
File X.py
def X1:
return "x1"
from Y import Y2
def X2:
return "x2"
File Y.py
def Y1:
return "y1"
from X import X1
def Y2:
return "y2"
Now suppose you compile file X.py. The compiler begins by defining the method X1, and then hits the import statement in X.py. This causes the compiler to pause compilation of X.py and begin compiling Y.py. Shortly thereafter the compiler hits the import statement in Y.py. Since X.py is already in the module table, Python uses the existing incomplete X.py symbol table to satisfy any references requested. Any symbols appearing before the import statement in X.py are now in the symbol table, but any symbols after are not. Since X1 now appears before the import statement, it is successfully imported. Python then resumes compiling Y.py. In doing so it defines Y2 and finishes compiling Y.py. It then resumes compilation of X.py, and finds Y2 in the Y.py symbol table. Compilation eventually completes w/o error.
Something very different happens if you attempt to compile Y.py from the command line. While compiling Y.py, the compiler hits the import statement before it defines Y2. Then it starts compiling X.py. Soon it hits the import statement in X.py that requires Y2. But Y2 is undefined, so the compile fails.
Please note that if you modify X.py to import Y1, the compile will always succeed, no matter which file you compile. However if you modify file Y.py to import symbol X2, neither file will compile.
Any time when module X, or any module imported by X might import the current module, do NOT use:
from X import Y
Any time you think there may be a circular import you should also avoid compile time references to variables in other modules. Consider the innocent looking code:
import X
z = X.Y
Suppose module X imports this module before this module imports X. Further suppose Y is defined in X after the import statement. Then Y will not be defined when this module is imported, and you will get a compile error. If this module imports Y first, you can get away with it. But when one of your co-workers innocently changes the order of definitions in a third module, the code will break.
In some cases you can resolve circular dependencies by moving an import statement down below symbol definitions needed by other modules. In the examples above, definitions before the import statement never fail. Definitions after the import statement sometimes fail, depending on the order of compilation. You can even put import statements at the end of a file, so long as none of the imported symbols are needed at compile time.
Note that moving import statements down in a module obscures what you are doing. Compensate for this with a comment at the top of your module something like the following:
#import X (actual import moved down to avoid circular dependency)
In general this is a bad practice, but sometimes it is difficult to avoid.
For those of you who, like me, come to this issue from Django, you should know that the docs provide a solution:
https://docs.djangoproject.com/en/1.10/ref/models/fields/#foreignkey
"...To refer to models defined in another application, you can explicitly specify a model with the full application label. For example, if the Manufacturer model above is defined in another application called production, you’d need to use:
class Car(models.Model):
manufacturer = models.ForeignKey(
'production.Manufacturer',
on_delete=models.CASCADE,
)
This sort of reference can be useful when resolving circular import dependencies between two applications...."
I was able to import the module within the function (only) that would require the objects from this module:
def my_func():
import Foo
foo_instance = Foo()
If you run into this issue in a fairly complex app it can be cumbersome to refactor all your imports. PyCharm offers a quickfix for this that will automatically change all usage of the imported symbols as well.
I was using the following:
from module import Foo
foo_instance = Foo()
but to get rid of circular reference I did the following and it worked:
import module.foo
foo_instance = foo.Foo()
According to this answer we can import another module's object in the block( like function/ method and etc), without circular import error occurring, for example for import Simple object of another.py module, you can use this:
def get_simple_obj():
from another import Simple
return Simple
class Example(get_simple_obj()):
pass
class NotCircularImportError:
pass
In this situation, another.py module can easily import NotCircularImportError, without any problem.
just check your file name see if it is not the same as library you are importing.
Eg - sympy.py
import sympy as sym

When is the name imported? And which namespace is it in? [duplicate]

I am learning Python and am still a beginner, although I have been studying it for about a year now. I am trying to write a module of functions which is called within a main module. Each of the functions in the called module needs the math module to run. I am wondering if there is a way to do this without importing the math module inside the called module. Here is what I have:
main.py:
from math import *
import module1
def wow():
print pi
wow()
module1.cool()
module1.py:
def cool():
print pi
When running main.py I get:
3.14159265359
Traceback (most recent call last):
File "Z:\Python\main.py", line 10, in <module>
module1.cool()
File "Z:\Python\module1.py", line 3, in cool
print pi
NameError: global name 'pi' is not defined
What I'm having a hard time understanding is why I get a name error when running main.py. I know that the variable pi becomes global to the main module upon import because wow can access it. I also know that cool becomes global to the main module upon import because I can print module1.cool and get <function cool at 0x02B11AF0>. So since cool is inside the global namespace of the main module, shouldn't the program first look inside the function cool for the variable pi, and then when it doesn't find it there, look inside main module for the variable pi and find it there?
The only way to get around this that I know of is to import the math module inside module1.py. I don't like the idea of that, though because it makes things more complicated and I am a fan of nice, simple code. I feel like I am close to grasping namespaces, but need help on this one. Thanks.
As the traceback shows, the problem isn't in main.py, but in module1.py:
Traceback (most recent call last):
File "Z:\Python\main.py", line 10, in <module>
module1.cool()
File "Z:\Python\module1.py", line 3, in cool
print pi
NameError: global name 'pi' is not defined
In other words, in module1, there is no global name pi, because you haven't imported it there. When you do from math import * in main.py, that just imports everything from the math module's namespace into the main module's namespace, not into every module's namespace.
I think the key thing you're missing here is that each module has its own "global" namespace. This can be a bit confusing at first, because in languages like C, there's a single global namespace shared by all extern variables and functions. But once you get past that assumption, the Python way makes perfect sense.
So, if you want to use pi from module1, you have to do the from math import * in module1.py. (Or you could find some other way to inject it—for example, module1.py could do from main import *, or main.py could do module1.pi = pi, etc. Or you could cram pi into the magic builtins/__builtin__ module, or use various other tricks. But the obvious solution is to do the import where you want it imported.)
As a side note, you usually don't want to do from foo import * anywhere except the interactive interpreter or, occasionally, the top-level script. There are exceptions (e.g., a few modules are explicitly designed to be used that way), but the rule of thumb is to either import foo or use a limited from foo import bar, baz.
"Explicit is better than implicit" is a design decision that was made by the creators of Python (launch python and run import this).
Therefore, when you run module1.cool(), Python will not look for the undefined pi in the main module.
You'll have to import the math module in explicitly whenever you want to use it - that's just how Python works.
Also, you should avoid from X import *-style imports, that's bad practice too. Here, you could do: from math import pi.
As others have said, there isn't actually a global pi in your module1. A good solution for you is this, which only imports pi once from math and explicitly ensures that the pi you're getting is the one from module1:
main.py:
import module1
def wow():
print module1.pi
wow()
module1.cool()
module1.py:
from math import pi
def cool():
print pi
The simple approach of exec (python 3) or execfile (python 2) as mentioned in the comments by #abarnert may be useful for some workflows. All that is needed is to replace the import line with:
exec( open("module1.py").read() ) # python 3
and then you can simply call the function with cool() rather than module1.cool(). Within cool(), the variable pi will behave like a global, as the OP had originally expected.
In a nutshell, this is simply hiding a function definition that would otherwise appear at the top of your main program and has both advantages and disadvantages. For large projects with multiple modules and imports, using exec (instead of a proper namespaces) is probably a mistake as you don't generally want to keep too many things within a single global namespace.
But for simple cases (like using Python as a shell script) exec gives you a simple and concise way to hide shared functions while letting them share the global namespace. Just note that in this case you might want to give extra thought to how you name your functions (e.g. use v1_cool and v2_cool to keep track of different versions since you can't do v1.cool and v2.cool).
One less obvious disadvantage of using exec here is that errors in the executed code may not display the line number of the error although you can work around this: how to get the line number of an error from exec or execfile in Python
Inside the module you could simply define from math import pi, which would only import pi from math but not the entire math module.

Why do circular imports seemingly work further up in the call stack but then raise an ImportError further down?

I'm getting this error
Traceback (most recent call last):
File "/Users/alex/dev/runswift/utils/sim2014/simulator.py", line 3, in <module>
from world import World
File "/Users/alex/dev/runswift/utils/sim2014/world.py", line 2, in <module>
from entities.field import Field
File "/Users/alex/dev/runswift/utils/sim2014/entities/field.py", line 2, in <module>
from entities.goal import Goal
File "/Users/alex/dev/runswift/utils/sim2014/entities/goal.py", line 2, in <module>
from entities.post import Post
File "/Users/alex/dev/runswift/utils/sim2014/entities/post.py", line 4, in <module>
from physics import PostBody
File "/Users/alex/dev/runswift/utils/sim2014/physics.py", line 21, in <module>
from entities.post import Post
ImportError: cannot import name Post
and you can see that I use the same import statement further up and it works. Is there some unwritten rule about circular importing? How do I use the same class further down the call stack?
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 What can I do about "ImportError: Cannot import name X" or "AttributeError: ... (most likely due to a circular import)"? for techniques for resolving and avoiding circular dependencies.
I think the answer by jpmc26, while by no means wrong, comes down too heavily on circular imports. They can work just fine, if you set them up correctly.
The easiest way to do so is to use import my_module syntax, rather than from my_module import some_object. The former will almost always work, even if my_module included imports us back. The latter only works if my_object is already defined in my_module, which in a circular import may not be the case.
To be specific to your case: Try changing entities/post.py to do import physics and then refer to physics.PostBody rather than just PostBody directly. Similarly, change physics.py to do import entities.post and then use entities.post.Post rather than just Post.
When you import a module (or a member of it) for the first time, the code inside the module is executed sequentially like any other code; e.g., it is not treated any differently that the body of a function. An import is just a command like any other (assignment, a function call, def, class). Assuming your imports occur at the top of the script, then here's what's happening:
When you try to import World from world, the world script gets executed.
The world script imports Field, which causes the entities.field script to get executed.
This process continues until you reach the entities.post script because you tried to import Post
The entities.post script causes physics module to be executed because it tries to import PostBody
Finally, physics tries to import Post from entities.post
I'm not sure whether the entities.post module exists in memory yet, but it really doesn't matter. Either the module is not in memory, or the module doesn't yet have a Post member because it hasn't finished executing to define Post
Either way, an error occurs because Post is not there to be imported
So no, it's not "working further up in the call stack". This is a stack trace of where the error occurred, which means it errored out trying to import Post in that class. You shouldn't use circular imports. At best, it has negligible benefit (typically, no benefit), and it causes problems like this. It burdens any developer maintaining it, forcing them to walk on egg shells to avoid breaking it. Refactor your module organization.
To understand circular dependencies, you need to remember that Python is essentially a scripting language. Execution of statements outside methods occurs at compile time. Import statements are executed just like method calls, and to understand them you should think about them like method calls.
When you do an import, what happens depends on whether the file you are importing already exists in the module table. If it does, Python uses whatever is currently in the symbol table. If not, Python begins reading the module file, compiling/executing/importing whatever it finds there. Symbols referenced at compile time are found or not, depending on whether they have been seen, or are yet to be seen by the compiler.
Imagine you have two source files:
File X.py
def X1:
return "x1"
from Y import Y2
def X2:
return "x2"
File Y.py
def Y1:
return "y1"
from X import X1
def Y2:
return "y2"
Now suppose you compile file X.py. The compiler begins by defining the method X1, and then hits the import statement in X.py. This causes the compiler to pause compilation of X.py and begin compiling Y.py. Shortly thereafter the compiler hits the import statement in Y.py. Since X.py is already in the module table, Python uses the existing incomplete X.py symbol table to satisfy any references requested. Any symbols appearing before the import statement in X.py are now in the symbol table, but any symbols after are not. Since X1 now appears before the import statement, it is successfully imported. Python then resumes compiling Y.py. In doing so it defines Y2 and finishes compiling Y.py. It then resumes compilation of X.py, and finds Y2 in the Y.py symbol table. Compilation eventually completes w/o error.
Something very different happens if you attempt to compile Y.py from the command line. While compiling Y.py, the compiler hits the import statement before it defines Y2. Then it starts compiling X.py. Soon it hits the import statement in X.py that requires Y2. But Y2 is undefined, so the compile fails.
Please note that if you modify X.py to import Y1, the compile will always succeed, no matter which file you compile. However if you modify file Y.py to import symbol X2, neither file will compile.
Any time when module X, or any module imported by X might import the current module, do NOT use:
from X import Y
Any time you think there may be a circular import you should also avoid compile time references to variables in other modules. Consider the innocent looking code:
import X
z = X.Y
Suppose module X imports this module before this module imports X. Further suppose Y is defined in X after the import statement. Then Y will not be defined when this module is imported, and you will get a compile error. If this module imports Y first, you can get away with it. But when one of your co-workers innocently changes the order of definitions in a third module, the code will break.
In some cases you can resolve circular dependencies by moving an import statement down below symbol definitions needed by other modules. In the examples above, definitions before the import statement never fail. Definitions after the import statement sometimes fail, depending on the order of compilation. You can even put import statements at the end of a file, so long as none of the imported symbols are needed at compile time.
Note that moving import statements down in a module obscures what you are doing. Compensate for this with a comment at the top of your module something like the following:
#import X (actual import moved down to avoid circular dependency)
In general this is a bad practice, but sometimes it is difficult to avoid.
For those of you who, like me, come to this issue from Django, you should know that the docs provide a solution:
https://docs.djangoproject.com/en/1.10/ref/models/fields/#foreignkey
"...To refer to models defined in another application, you can explicitly specify a model with the full application label. For example, if the Manufacturer model above is defined in another application called production, you’d need to use:
class Car(models.Model):
manufacturer = models.ForeignKey(
'production.Manufacturer',
on_delete=models.CASCADE,
)
This sort of reference can be useful when resolving circular import dependencies between two applications...."
I was able to import the module within the function (only) that would require the objects from this module:
def my_func():
import Foo
foo_instance = Foo()
If you run into this issue in a fairly complex app it can be cumbersome to refactor all your imports. PyCharm offers a quickfix for this that will automatically change all usage of the imported symbols as well.
I was using the following:
from module import Foo
foo_instance = Foo()
but to get rid of circular reference I did the following and it worked:
import module.foo
foo_instance = foo.Foo()
According to this answer we can import another module's object in the block( like function/ method and etc), without circular import error occurring, for example for import Simple object of another.py module, you can use this:
def get_simple_obj():
from another import Simple
return Simple
class Example(get_simple_obj()):
pass
class NotCircularImportError:
pass
In this situation, another.py module can easily import NotCircularImportError, without any problem.
just check your file name see if it is not the same as library you are importing.
Eg - sympy.py
import sympy as sym

import module_name Vs __import__('module_name')

I am writing a python module and I am using many imports of other different modules.
I am bit confused that whether I should import all the necessary dependent modules in the opening of the file or shall I do it when necessary.
I also wanted to know the implications of both.
I come from C++ back ground so I am really thrilled with this feature and does not see any reason of not using __import__(), importing the modules only when needed inside my function.
Kindly throw some light on this.
To write less code, import a module at the first lines of the script, e.g.:
#File1.py
import os
#use os somewhere:
os.path.chdir(some_dir)
...
...
#use os somewhere else, you don't need to "import os" everywhere
os.environ.update(some_dict)
While sometimes you may need to import a module locally (e.g., in a function):
abc=3
def foo():
from some_module import abc #import inside foo avoids you from naming conflicts
abc(...) #call the function, nothing to do with the variable "abc" outside "foo"
Don't worry about the time consumption when calling foo() multiple times, since import statements loads modules/functions only one time. Once a module/function is imported, the object is stored in dictionary sys.modules, which is a lookup table for speedup when running the same import statement.
As #bruno desthuilliers mentioned, importing insede functions may not be that pythonic, it violates PEP8, here's a discussion I found, you should stick to importing at the top of the file most of the time.
First, __import__ isn't usually needed anywhere. It's main purpose is to support dynamic importing of things that you don't know ahead of time (think plug-ins). You can easily use the import statement inside your function:
import sys
def foo():
import this
if __name__ == "__main__":
print sys.version_info
foo()
The main advantage to importing everything up-front is that it is most customary. That's where people reading your code will go to see if something is imported or not. Also, you don't need to write import os in every function that uses os. The main downsides of this approach are that:
you can get yourself into unresolvable import loops (A imports B which imports A)
that you pull everything into memory even if you aren't going to use it.
The second problem isn't typically an issue -- very rarely do you notice the performance or memory impact of an import.
If you run into the first problem, it's likely a symptom of poorly grouped code and the common stuff should be factored into a new module C which both A and B can use.
Firstly, it's a violation of PEP8 using imports inside functions.
Calling import it's an expensive call EVEN if the module is already loaded, so if your function is gonna being called many times this will not compensate the performance gain.
Also when you call "import test" python do this:
dataFile = __ import__('test')
The only downside of imports at the top of file it's the namespace that get polluted very fast depending on complexity of the file, but if your file it's too complex it's a signal of bad design.

Working with static class variables in Python

Python won't allow me to import classes into eachother. I know there is no "package" solution in Python, so I'm not sure how this could be done. Take a look at my files' codes:
file Main.py:
from Tile import tile
tile.assign()
class main:
x = 0
#staticmethod
def assign():
tile.x = 20
file Tile.py:
from Main import main
main.assign()
class tile:
x = 0
#staticmethod
def assign():
main.x = 20
I get the error "class tile can not be imported".
If file A imports file B, and file B imports file A, they would keep importing each other indefinitely until the program crashed.
You need to rethink your logic in a way that doesn't require this circular dependency. For example, a 3rd file could import both files and perform both assignments.
You have your import backwards and the from needs to have the name of the module
from Tile import tile
Python begins executing Main.py. It sees the import, and so goes to execute Tile.py. Note that it has not yet executed the class statement!
So Python begins executing Tile.py. It sees an import from Main, and it already has that module in memory, so it doesn't re-execute the code in Main.py (even worse things would go wrong if it did). It tries to pull out a variable main from the Main module, but the class statement binding main hasn't executed yet (we're still in the process of executing the import statement, advice that line). So you get the error about there not being a clsss main in module Main (or Tile, if you started from there).
You could avoid that by importing the modules rather than importing classes out of the modules, and using qualified names, but then you'd fall one line down when Main.main doesn't work. Your code makes no sense I'm a dynamic language; you can't have both the definition of class main wait until after tile.assign has been called and the definition of class tile wait until after main.assign has been called.
If you really need this circular dependency (it's often, but not always a sign that something has gone wrong at the design stage), then you need to separate out "scaffolding" like defining classes and functions and variables from "execution", where you actually call classes and functions or use variables. Then your circular imports of the "scaffolding" will work even though none of the modules will be properly initialized while the importing is going on, and by the time you get to starting the "execution" everything will work.

Categories

Resources