View more

View more

View more

Image of the Day Submit

IOTD | Top Screenshots

The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

Python global variable problem

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

11 replies to this topic

#1King Mir  Members

Posted 26 June 2012 - 07:14 AM

So I have 3 files like so:
[source lang="python"]#Test1.pyimport Test2, Test.Test3if __name__ == '__main__': Test2.initVal() print Test2.getVal() Test.Test3.func()[/source]
[source lang="python"]#Test2.pyval = {}def initVal(): val[0] = 1 def getVal(): return val[0][/source]
[source lang="python"]#Test/Test3.pyimport Blobs.Test2def func(): print Blobs.Test2.getVal() #blobs is top level package[/source]

This prints 1, then gives me an exception, because func() sees val as empty the second time. How do I make it see the properly changed variable?

EDIT: clarified behavior

Edited by King Mir, 26 June 2012 - 04:39 PM.

#2ColinDuquesnoy  Members

Posted 26 June 2012 - 12:26 PM

This is because you need to specifiy you are using a global.

Your initVal and getVal functions should look like this:

def initVal():
global val
val[0] = 1

def getVal():
global val
return val[0]


#3King Mir  Members

Posted 26 June 2012 - 01:29 PM

This is because you need to specifiy you are using a global.

Your initVal and getVal functions should look like this:

def initVal():
global val
val[0] = 1

def getVal():
global val
return val[0]


Tried it, didn't work.

From what I understand, global is used to spefiy that assign ment should overide a global variable. It would be needed to make Test2.getVal() work the first time, if the dictionary was reassigned, instead of having a key added. Here Test2.getVal() works, just not Blobs.Test2.getVal(),

#4ColinDuquesnoy  Members

Posted 26 June 2012 - 02:29 PM

This is working fine for me, both function return 1. What is the exact error. What do you mean by it does not work? Could you provide the project structure? (packages layout)

From what I understand, global is used to spefiy that assign ment should overide a global variable. It would be needed to make Test2.getVal() work the first time, if the dictionary was reassigned, instead of having a key added

I'm not sure to understand what you mean. Global is used to tell the interpreter that you are not dealing with a new object but reusing/overriding one that was defined at global scope when the module was imported the first time. So in any case (assignement or adding a key), "global val" is needed.

#5King Mir  Members

Posted 26 June 2012 - 04:04 PM

The package layout is that Test3.py is in a package Test, and everything is in a package Blob (including package Test).

The error is that it prints 1, then throws a key error for the second call.

#6King Mir  Members

Posted 26 June 2012 - 11:53 PM

I also found this surprising behaviour:

[source lang="python"]#Test5.pyimport Blobs.Test2def func2(atype): print atype print Blobs.Test2.TestClass print atype == Blobs.Test2.TestClass[/source]
[source lang="python"]#Test2.pyclass TestClass (object): pass[/source]

[source lang="python"]import Test5, Test2if __name__ == '__main__': Test5.func2(Test2.TestClass)[/source]

This prints 2 different class paths, followed by False. Why? It's the same class, just a different way of getting to it.

#7ColinDuquesnoy  Members

Posted 27 June 2012 - 12:49 AM

It seems all those issues come from the fact that you are importing the Test2.py differently.

Sometimes you use
import Blobs.Test2
and sometimes
import Test2

Python treats it as if it were two different modules. To fix your problem always use import Blobs.xxx (where xxx is the name of your module/package)

#8King Mir  Members

Posted 27 June 2012 - 12:05 PM

I see. Thanks.

That's very annoying. It means I'll have to use absolute paths for all imports. And probably use from import for brevity,

#9ColinDuquesnoy  Members

Posted 27 June 2012 - 12:45 PM

If you plan to distribute the package (or use it in different projects), yes. Otherwise you can just omit the package name (in this case you should even remove the __ini__.py as it is not a real package anymore).

Edited by renega_666, 27 June 2012 - 12:47 PM.

#10King Mir  Members

Posted 27 June 2012 - 01:47 PM

Do you mean leave the folder structure, but remove the __init__.py from the Test folder? Or remove the Blobs package but leave Test intact?

Right now I have a package, like Test in this question, that needs to call a function 1 package up. Eventually I might add enough to the program that that function and related code would warrant a package of its own. So the solution needs to have that in mind.

Though I am using packages for organisational convenience, not really to be able to reuse the code in another program.

#11ColinDuquesnoy  Members

Posted 27 June 2012 - 03:56 PM

I mean removing the __init__.py from the blobs folder and replacing

#Test/Test3.py
import Blobs.Test2

def func():
print Blobs.Test2.getVal() #blobs is top level package


by

#Test/Test3.py
import Test2

def func():
print Test2.getVal() #blobs is not a top level package anymore, this is just the project dir


When writing a python application, I usually follow this layout:

ProjectDir/
main.py
config.py
package1/
__init__.py
file1.py
file2.py
package2/
__init__.py
file1.py
file2.py


As package1 and package2 directories contains a __init__.py, I can do the following in the main script:

# main.py
import package1.file1
import package1.file2
import package2.file1
import package2.file2
def test():
package1.file1.a_func()
package1.file2.a_func()
package2.file1.a_func()
package2.file2.a_func()


And nothing prevents me to use the configuration module from the package1.file1 module:

import config
"""
no need to specify path as config.py sits in the same directory  as the main.py (path is added to
sys.path automatically when the main script is started so python knows about all other files on the same level as the main script)
"""
def a_func():
print(config.a_value)


Edit: clarified last docstring + a typo

Edited by renega_666, 27 June 2012 - 04:03 PM.

#12King Mir  Members

Posted 27 June 2012 - 06:17 PM

Thanks, I'll try that.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.