I'm trying to make a simple game, which has multiple files that need to import each other. My mob module needs to import my player module and do player = player.Player() to create a new class instance. The class is in the player.py file, but it's apparently not being recognized.
I did world = world.World() in my mob file, and that worked perfectly, so I'm confused as to why my player file won't work.
player.__file__ shows the correct path so that's not the issue.
This is what I have at the beginning of mob.py:
import world
import main
import player
world = world.World()
player = player.Player()
class Mob:
#Class definition
player.py:
import main
import world
world = world.World()
class Player:
#Definition
world.py:
import os
import main
class World:
#Definition
Not sure if this will help, but this is the main function in main.py:
if __name__ == "__main__":
console = []
player = player.Player()
movePlayer = player.Move
transformPlayer = player.Transform
goblin = mob.Mob()
world = world.World()
mapSize = world.MapSize
mainMenu()
The problem here is a circular import.
Since you haven't given us enough of the code to actually test this, it's impossible to give the exact details. If you want to see it for yourself, just add a print before and after each import, and you can see the sequence of events. But it's going to be something like this:
player depends on main. main depends on mob. So, when you try to import player, before it can run any of its top-level code, all of mob's top-level code has to run. But mob tries to create a player.Player object at top level. Since player is still waiting for import main to finish, it hasn't yet run the code to define that class. Hence the error.
The official FAQ has a nice answer on different ways to fix this. In your case, I think there's a simple answer:
Split main.py into two separate modules. Take the shared code that everyone else needs to import, and put it into, say, utils.py. Leave the top-level program code that needs to import everyone else in main.py. Change each import main to import utils. And that's it; no more circular imports. (This is effectively Matthias Ulrichs's recommendation from the FAQ, but more specific to your situation—and, as it happens, very common among projects created by novices to Python, especially those who are very skilled at languages that have separate import and implementation files.)
If this isn't doable in your case, consider moving some of the global initialization to initialization functions, which you can call after all the imports are done. (This is effectively Guido's recommendation from the FAQ.)
Related
I've found plenty about calling variables from another module, but I can't find anything about editing a variable in a separate module.
For my first actual project with python I'm writing a little text adventure.
I've got GV.py for global variables, and Classes.py for weapons/armor etc.
I want Classes.Longsword() to modify a variable in GV.py, specifically variable GV.weapon.
In GV.py
import Classes
global weapon
weapon = 'Unarmed'
in Classes.py
import GV
def Longsword():
GV.weapon = 'Longsword'
This does not edit the variable weapon in GV.py.. Am I missing something?
Since it was asked I'll put the output here.
repl from GV.py
weapon
'Unarmed'
Classes.Longsword()
>>>>
weapon
'Unarmed'
Your problem is that, when you run the script GV.py, what you get isn't a module named GV, but a special module named __main__.
If you've seen the familiar main guard idiom, that can be used to write a single file that works as a module or as a top-level script, this is exactly how it works:
if __name__ == '__main__':
That will be true when you're running the file as a script, and it will not be true when you're importing the file as a module.
Now, when you do import GV from inside Classes, that imports the exact same GV.py file, and builds a second module object out of it (and this one, of course, is named GV).
So when you then do GV.weapon = 'longsword', you're changing the weapon global in the GV module, not the __main__ module.
If you're wondering how this works under the covers: the way Python makes sure there's only one Classes module object no matter how many times you import Classes is dead simple: it just caches loaded modules in a dict, sys.modules, and looks them up by name.
If you fix that, you've got a second problem here: the first thing GV.py does is to import Classes. The first thing Classes.py does is to import GV. This is a circular import.
The usual way to deal with both of these problems is pretty simple: put the shared globals in a simple module that does little or nothing beyond holding those shared globals, so everyone can import it:
# main.py
import classes
import GV
GV.weapon = 'Unarmed'
# Classes.py
import GV
def Longsword():
GV.weapon = 'Longsword'
# GV.py
# empty... or you can move weapon = 'Unarmed' here
I am a python beginne, and am currently learning import modules in python.
So my question is:
Suppose I currently have three python files, which is module1.py, module2.py, and module3.py;
In module1.py:
def function1():
print('Hello')
In module2.py, in order to use those functions in module1.py:
import module1
#Also, I have some other public functions in this .py file
def function2():
print('Goodbye')
#Use the function in module1.py
if __name__ == '__main__':
module1.function1();
function2();
In module3.py, I would like to use both the functions from module1.py and module2.py.
import module1
import module2
def function3():
print('Nice yo meet you');
if __name__ == '__main__':
module1.function1()
function3()
module2.function2()
Seems like it works. But my questions are mainly on module3.py. The reason is that in module3.py, I imported both module1 and module2. However, module1 is imported by module2 already. I am just wondering if this is a good way to code? Is this effective? Should I do this? or Should I just avoid doing this and why?
Thank you so much. I am just a beginner, so if I ask stupid questions, please forgive me. Thank you!!
There will be no problem if you avoid circular imports, that is you never import a module that itself imports the current importing module.
A module does not see the importer namespace, so imports in the importer code don't become globals to the imported module.
Also module top-level code will run on first import only.
Edit 1:
I am answering Filipe's comments here because its easier.
"There will be no problem if you avoid circular imports" -> This is incorrect, python is fine with circular imports for the most part."
The fact that you sensed some misconception of mine, doesn't make that particular statement incorrect. It is correct and it is good advice.
(Saying it's fine for the most part looks a bit like saying something will run fine most of time...)
I see what you mean. I avoid it so much that I even thought your first example would give an error right away (it doesn't). You mean there is no need to avoid it because most of the time (actually given certain conditions) Python will go fine with it. I am also certain that there are cases where circular imports would be the easiest solution. That doesn't mean we should use them if we have a choice. That would promote the use of a bad architecture, where every module starts depending on every other.
It also means the coder has to be aware of the caveats.
This link I found here in SO states some of the worries about circular imports.
The previous link is somewhat old so info can be outdated by newer Python versions, but import confusion is even older and still apllies to 3.6.2.
The example you give works well because relevant or initialization module code is wrapped in a function and will not run at import time. Protecting code with an if __name__ == "__main__": also removes it from running when imported.
Something simple like this (the same example from effbot.org) won't work (remember OP says he is a beginner):
# file y.py
import x
x.func1()
# file x.py
import y
def func1():
print('printing from x.func1')
On your second comment you say:
"This is also incorrect. An imported module will become part of the namespace"
Yes. But I didn't mention that, nor its contrary. I just said that an imported module code doesn't know the namespace of the code making the import.
To eliminate the ambiguity I just meant this:
# w.py
def funcw():
print(z_var)
# z.py
import w
z_var = 'foo'
w.funcw() # error: z_var undefined in w module namespace
Running z.py gives the stated error. That's all that I meant.
Now going further, to get the access we want, we go circular...
# w.py
import z # go circular
def funcw():
'''Notice that we gain access not to the z module that imported
us but to the z module we import (yes its the same thing but
carries a different namespace). So the reference we obtain
points to a different object, because it really is in a
different namespace.'''
print(z.z_var, id(z.z_var))
...and we protect some code from running with the import:
# z.py
import w
z_var = ['foo']
if __name__ == '__main__':
print(z_var, id(z_var))
w.funcw()
By running z.py we confirm the objects are different (they can be the same with immutables, but that is python kerning - internal optimization, or implementation details - at work):
['foo'] 139791984046856
['foo'] 139791984046536
Finally I agree with your third comment about being explicit with imports.
Anyway I thank your comments. I actually improved my understanding of the problem because of them (we don't learn much about something by just avoiding it).
I want to know which way the best is for importing modules.
I'm currently using multiple files for my Pygame-Game. There are the main files and there is also a file where I import everything from.
It's like this:
settings.py:
import pygame,random,os,...
a main game file:
from settings import pygame
Everything works fine but should I do it instead like this?
a main game file(rewriten):
import pygame
The first way to import modules implies that there's a reason you import pygame from settings and not directly.
You might have modified some variables, functions or objects from pygame in settings.py, so that the stuff imported from settings.pygame has different behavior than that imported from pygame directly.
Just for the sake of an example (of how not to do it I'd say):
Say your pygame.py has a function like:
enemy_action( In_1, ... , In_n, DIFFICULTY )
In your settings.py you now probably have the difficulty setting stored, so you could redefine the function with DIFFICULTY already set by creating a decorator for the function:
pygame.DIFFICULTY = DIFFICULTY
def pygame.difficulty_setter(f):
def inner(*x, DIFFICULTY = pygame.DIFFICULTY):
return f(*x,DIFFICULTY = pygame.DIFFICULTY)
return inner
If you now set
enemy_action = pygame.difficulty_setter(enemy_action)
The function enemy_action wouldn't need to be passed the DIFFICULTY parameter anymore.
As the link bellow said, import necessary modules in another module, is a good shape looking code. For large projects it is a necessary work, because every thing going to be crazy.
Python import modules in another file
well, as the title say, i got a group of import, all import a class, all in the same folder as the script running it:
from lvl import lvl
from get import get
from image import image
from video import vid
from video import MLStripper
from system import system
from setting import setting
from listsearch import lists
python3 doesn't have reload iirc but there is imp.reload() but it doesn't seem to work,
it just throw a error saying it not a module (it a class so it doesn't work)
after every little edit in those class that are imported, i would need to restart the script
isn't there a way to reload/reimport the class to show the effect of the edit without needing to start the script or rewriting most of the script so that imp.reload() works?
python3, linux (but prefer if it also work on window)
edit1:
example: if i use:
import system
system.system.temp()
it return:
65°C
if i change it to show °F and reload it using imp.reload
imp.reload(system)
system.system.temp()
it return:
149°F
so, it works BUT if i use
import system as _system
from system import system
system.temp()
it return:
65°C
then i change it to show °F and reload it using imp.reload
imp.reload(_system)
from system import system
system.temp()
it still return
65°C
BUT again, if i call it this way:
_system.system.temp()
it return
149°F
idk why it that but it is cause it happen in a while loop?
edit2:
file name: system.py:
before changing for test:
class system:
def temp():
temperature = open("/sys/class/thermal/thermal_zone0/temp","r").read()
temperature = temperature[:2]
return(temperature+"°C")
after changing for test:
class system:
def temp():
temperature = open("/sys/class/thermal/thermal_zone0/temp","r").read()
temperature = temperature[:2]
temperature = str(9.0 / 5.0 * int(temperature) + 32).split(".")[0]
return(temperature+"°C")
You can only reload a module:
The argument must be a module object, so it must have been successfully imported before.
In your case, you don't have any reference to the module object. You will have to import it, even if you don't want to use it for anything else, just for the sake of calling reload later.
Also, after the reload, you have re-import the names:
Other references to the old objects (such as names external to the module) are not rebound to refer to the new objects and must be updated in each namespace where they occur if that is desired.
When you do from foo import bar, that bar is a "name external to the module", so you have to rebind it explicitly.
If you think about it, it has to work this way. There's no way reload can enumerate all objects whose definition is dependent on the previous version of the module to update them. Even if it could, there could be infinite cycles. And what would happen if the new version didn't even have a definition for a class that was in the old one? Or if the class were defined dynamically?
Looking at it another way, from foo import bar is very similar to import foo; bar = foo.bar. bar is a name in your namespace, not foo's namespace, so reload(foo) will not touch it; you need to copy the new foo.bar over again.
The easy way to solve all of these problems is to just repeat all of your from foo import bar lines after the reload.
For simple cases:
import video
from video import MLStripper
# ... later
imp.reload(video)
from video import MLStripper
However, most of your examples have an obvious naming conflict: once you from video import video, you can no longer reload(video). So, you need another reference to the video module object.
Python keeps one around for you, which you can use:
imp.reload(sys.modules['video'])
from video import MLStripper
Or, alternatively, you can use an as clause, or just an = assignment, to give it whatever name you want.
import video as _video
from video import video
# ... later
imp.reload(_video)
from video import video
From your comments and your edited question, it sounds like you have a further problem. Let's use one of the simple non-colliding cases to discuss it.
I believe you're actually doing something like this:
import video
from video import MLStripper
stripper = MLStripper('foo")
# ... later
imp.reload(video)
from video import MLStripper
The first line will successfully reload the video module, and the second will copy its MLStripper class into your globals, so any new MLStripper instances you created will be of the new type.
But that doesn't affect any existing MLStripper instances, like stripper.
Just like MLStripper was, stripper is one of those "names external to the module". But it's actually even worse. In order to adjust it, reload would have to figure out what its state would have been, had the new version of the code been in effect from the time it was created. It should be obvious that this is an unsolvable problem.
If you know the instances you want to patch up, you can deal with them in effectively the same way you dealt with the classes: just create them again:
imp.reload(video)
from video import MLStripper
stripper = MLStripper('foo")
If that's not good enough, there are three hacky possibilities that may be what you want:
Monkeypatch the methods, attributes, etc. into the instance(s) and their __class__(es).
Patch the instances' __class__ attribute directly, so anything that was inherited from the class will now be inherited from the new class.
Serialize the instances with pickle before the reload, then deserialize after.
For very simple cases, all three of these will work. For more complex cases, you will have to understand what you're doing.
Note that you can wrap a lot of this stuff up in a function, but you have to understand how locals and globals work (and how import and reload work) or you're going to end up confusing yourself.
A simpler solution is to just create "dump all state" and "load all state" functions. Then you can dump everything, quit, relaunch, and restore. The Python tutorial and the ipython docs both describe a few different ways to do this in place of using reload; it's probably worth going back and rereading those.
Access the module through sys.modules, reload that, then reassign the imported names:
imp.reload(sys.modules['lvl'])
from lvl import lvl
imp.reload(sys.modules['get'])
from get import get
etc.
All the from something import name syntax does is import something then bind name to the same object something.name refers to.
By using sys.modules you don't have to explicitly import the module again, and can reach the new definitions of the objects for rebinding after reloading.
Sorry if this is a very novice question, I was just wondering one thing.
When in python and your code is split up amongst multiple files, how would you avoid a ton of imports on the same thing?
Say I have 2 files. Main, and Content.
Main:
import pygame
from pygame.locals import *
pygame.display.init()
blah
Content:
import pygame
from pygame.locals import *
pygame.display.init()
load content and stuff
pygame is imported twice and display.init is called twice. This is problematic in other places. Is there anyway to get around this, or must it just import and import and import?
One situation I can think of is this: A script that writes to a file everytime it is imported. That way, if it's imported 3 times, it gets run 3 times, therefore writing to the file 3 times.
Thanks in advance!
You misunderstand what import does. It's not the same as include. Loaded modules are singletons and their corresponding files are not evaluated twice.
That said, a well-constructed module will not have side-effects on import. That's the purpose of the if __name__=='__main__' idiom.
Do not attempt to "clean up" your imports. Import everything you need to use from within a file. You could make less use of import *, but this is purely for code readability and maintainability.
You should avoid having anything happen at import(except, see further down). a python file is a module first, so it can and should be used by other python modules. If something "happens" in the import stage of a python file, then it may happen in an undesirable way when that file is imported by another module.
Each module should just define things to be used: classes, functions, constants, and just wait for something else to use them.
Obviously, if no script ever does at import, then it's not possible for anything to actually get used and make stuff "happen". There is a special idiom for the unusual case that a module was called directly. Each python file has a variable, __name__ automatically created with the module name it was imported as. When you run a script from the command line (or however you have started it), it wasn't imported, and there's no name for it to have, and so the __name__ variable will have a special value "__main__" that indicates that it's the script being executed. You can check for this condition and act accordingly:
# main.py
import pygame
from pygame.locals import *
import content
def init():
pygame.display.init()
def stuff():
content.morestuff()
if __name__ == '__main__':
init()
stuff()
# content.py
import pygame
from pygame.locals import *
def init():
pygame.display.init()
def morestuff():
"do some more stuff"
if __name__ == '__main__':
init()
morestuff()
This way; init() and thus pygame.display.init() are only ever called once, by the script that was run by the user. the code that runs assuming that init() has already been called is broken into another function, and called as needed by the main script (whatever that happens to be)
import statements are supposed to be declarations that you're using something from another module. They shouldn't be used to cause something to happen (like writing to a file). As noted by Francis Avila, Python will try not to execute the code of a module more than once anyway.
This has the consequence that whether a given import statement will cause anything to happen is a global property of the application at runtime; you can't tell just from the import statement and the source code of the module, because it depends on whether any other code anywhere else in the project has already imported that module.
So having a module "do something" when executed is generally a very fragile way to implement your application. There is no hard and fast definition of "do something" though, because obviously the module needs to create all the things that other modules will import from it, and that may involve reading config files, possibly even writing log files, or any number of other things. But anything that seems like the "action" of your program, rather than just "setting up" things to be imported from the module, should usually not be done in module scope.