I have the following situation:
The first file, named a.py contains:
var = 2
The second file, named b.py contains:
def prnt():
print(var)
The third file, named c.py contains:
from a import *
from b import *
prnt() # NameError: name 'var' is not defined
and raises the given error. I always thought that the import statement basically "copies" code into the calling namespace, so it should be the same as:
var = 2
def prnt():
print(var)
prnt()
but apparently this is not the case. What am I missing?
When you import a module, the code in that module is run by the interpreter (see this for example; add a print statement in there and you'll see it in action). Therefore you can't use variables etc without defining them or importing them.
In b.py do this at the top:
from a import var
Then, unless you need var in c.py, you won't need to import anything from a.py in c.py.
I know this is fake code, but avoid using globals in your functions.
Related
In a main *.py, the statement
from myModule import a,b,c
imports the module 'myModule', and creates references in the current namespace to the given objects. Or in other words, you can now use a and b and c in your program. But you need to use, for example:
print(myModule.a)
Now, I need to use the statement:
from myModule import *
and I need to access, in my main *.py file, at the values of some variables declared in 'myModule', for example:
print(a)
I tried to use globals() to declare global variables but then they are not imported in the current namespace.
Does anyone know hoe to solve this??
Thanks
Question isn't clear but you can import modules with any moniker you want with:
import thing as t
And to access:
t.thingFunction.(foo)
I'm confused about what happens if you tread a module as a singleton.
Say I have a module conf.py, that contains some configuration parameters which need to be accessed by multiple other files. In conf.py, I might have this piece of code (and nothing else):
myOption = 'foo' + 'bar'
If I now import it first in a.py, and then in b.py, my understanding is that the first time it is imported (in a.py), the string concatenation will be executed. But the second time it is imported (in b.py), conf.myOption already has its value, so no string concatenation will be executed. Is this correct?
If after doing these two imports, I then execute the following in b.py
conf.myOption = 'aDifferentFoobar'
then obviously b.py would now see this new value. Would a.py see the same value, or would it still see 'foobar'?
I believe (but correct me if I'm wrong) that imports are always referred to by reference, not by value? And I'm guessing that's what the above questions boil down to.
Try it and see:
mod.py:
def foo():
print("in foo()")
return "foo"
bar = foo()
opt = "initial"
b.py:
import mod
mod.opt = "changed"
a.py:
import mod
import b
print(mod.bar)
print(mod.opt)
Execute a.py:
$ python3.4 a.py
Output:
in foo()
foo
changed
We learn:
foo() is only executed once
mod.opt is changed by b.py
a.py sees the changed value of mod.opt
bonus: the order of imports in a.py does not matter
I have these 4 modules
globals.py
globvara = "a"
mod1.py
from globals import *
print globvara
output : a
mod2.py
from mod1 import *
def changegv(newval1):
#global globvara
globvara = newval1
def usechangegv(newval2):
changegv(newval2)
and mod3.py
from mod2 import *
usechangegv("b")
print globvara
output :
a
a
I am wondering why the globalvar does not change in module 2. I am missing something in global variables. Even if I uncomment the global globvara line I get the same result. Where is the error?
Python global variables are global only to modules. When you import a variable from another module (e.g. from mod1 import *), Python creates duplicate references to the value in the importing module. So you now have two names, mod1.globvara and mod2.globvara, which initially point to the same value, but which are not in any way connected. If you change globvara in mod2.py, you are changing mod2.globvara and mod1.globvara is not affected.
To avoid this problem, import the module, not the individual names defined in it. For example, import globals. Then always refer to globals.globvara (or better yet, globals.a). Since you are always accessing and assigning the same name, it will work the way you expect.
Don't use the
from <module> import <variable>
As it creates a copy of the variable.
Do a simple:
import <module>
And all accesses to the global variable should use the "variable" within "module":
<module>.<variable> = ...
or
print <module>.<variable>
I just finished the tutorial for making a rogue-like-game and I'm on my way to implement freatures.
The problem is, the whole game is a single file with 1k+ lines.
As you can see:
http://roguebasin.roguelikedevelopment.org/index.php?title=Complete_Roguelike_Tutorial,_using_python%2Blibtcod,_part_13_code
I want to divide it in different files/folders to handle the implements better.Maybe a file for each aspect of the game like map/player/npcs/items... but at least divide in Classes/Functions/Main.
The problem is, when I put this in the Main.py:
from Classes import *
from Functions import *
I get
NameError: name 'libtcod' is not defined
Which is a Module used in Main.
Then I tried to import the Main.py in the Classes.py and Functions.py
And get the
NameError: global name 'MAP_WIDTH' is not defined
MAP_WIDTH is a global variable in Main.py
I also tried to import the whole Main.py in Classes.py and Functions.py
But I get:
NameError: name 'Fighter' is not defined
Fighter is a Class inside Classes.py
Can anyone help me sort this out so I can start implement freatures.
EDIT: One simple example is:
Main.py
from Functions import *
def plus_one(ab):
return ab +1
a = 1
b = 2
c = add_things()
print plus_one(c)
Functions.py
from Main import *
def add_things():
global a,b
return a + b
It's a simple example, but in the project it get a lot of mutual dependecy between classes/functions and the main file.
There are many issues with your code and your planned program architecture. Please read my comment on your post. You need to shore up your knowledge of object oriented programming.
First, it is highly recommended to never use from Classes import *. You should use import Classes. Then to access functions or constants from the module you would use Classes.function_name or Classes.constant. See for more info on how to properly import in Python: http://effbot.org/zone/import-confusion.htm
Second, global variables are not recommended in Python. But if you do need them, you need to remember that in python a global variable means global to a module, not your entire program. Global variables in Python are a strange beast. If you need to read a global variable nothing special is required. However if you want to modify a global variable from within a function, then you must use the global keyword.
Thirdly, what you are doing is called a circle dependancy. Module A, imports Module B and Module B imports Module A. You can define shared functions, classes etc. in a third Module C. Then both A and B can import Module C. You can also defined your constants like MAP_WIDTH in module C and access them from A or B with C.MAP_WIDTH provided you have an import C.
Say I have a main module app.py which defines a global variable GLOBVAR = 123. Additionally this module imports a class bar located in another module foo:
from foo import bar
In the main module app I now call a method from the class bar. Within that method I want to access the value GLOBVAR from the main module app.
One straight-forward way would be to simply pass GLOBVAR to the method as parameter. But is there also another solution in Python that allows me to access GLOBVAR directly?
In module foo I tried one of the following:
from app import GLOBVAR # option 1
import app.GLOBVAR # option 2
However, both options lead to the following error at runtime:
ImportError: cannot import name bar
I understand this leads to a cyclic import between app and foo. So, is there a solution to this in Python, or do I have to pass the value as parameter to the function?
There are many ways to solve the same problem, and passing parameters is generally to be recommended. But if you do have some package wide global constants you can do that too. You will want to put these in a whole other module and import that module from both app and foo modules. If you build a package globals you can even put these in the __init__.py ... but another named module like settings or config can also be used.
For instance if you package layout is:
mypackage/
__init__.py
app.py
foo.py
config.py
Then:
config.py
GLOBVAR = 'something'
app.py
from mypackage.config import GLOBVAR
foo.py
from mypackage.config import GLOBVAR
if you just put the GLOBVAR in __init__.py then you would do from mypackage import GLOBVAR which could be prettier if you go for that sort of thing.
EDIT I'd also recommend using absolute imports even if you are using python 2, and always use the package name explicitly rather than relative imports for readability and because it makes things easier to split out later if you need to move something to a new different package
You can import a variable from the __main__ module like this:
""" main module """
import foo
name = "Joe"
foo.say_hi()
and foo.py:
""" foo module, to be imported from __main__ """
import __main__
def say_hi():
print "Hi, %s!" % __main__.name
and it looks like this:
$ python main.py
Hi, Joe!
Of course you can not access the variable before you define it. So you may need to put the access to __main__.name at function level, where it is evaluated after the import. In contrast to the module level, which is evaluated at the time of the import (where the variable not yet exists).
You should just write import line before where you want to use GLOBVAR this will prevent cycle!
In foo.py, the line
from app import GLOBVAR
must be after the bar class definition.
You can put GLOBVAR in a third module, import it into foo, and inside app import it from foo.
glob.py:
GLOBVAR=None
foo.py:
class bar:
global GLOBVAR
from glob.py import GLOBVAR
app.py:
from foo import GLOBVAR
import foo