Jump to content

  • Log In with Google      Sign In   
  • Create Account


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.

  • You cannot reply to this topic
11 replies to this topic

#1 King Mir   Members   -  Reputation: 1968

Like
0Likes
Like

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.


Sponsor:

#2 ColinDuquesnoy   Members   -  Reputation: 1114

Like
1Likes
Like

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]


#3 King Mir   Members   -  Reputation: 1968

Like
0Likes
Like

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(),

#4 ColinDuquesnoy   Members   -  Reputation: 1114

Like
1Likes
Like

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.

#5 King Mir   Members   -  Reputation: 1968

Like
0Likes
Like

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.

#6 King Mir   Members   -  Reputation: 1968

Like
0Likes
Like

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.

#7 ColinDuquesnoy   Members   -  Reputation: 1114

Like
1Likes
Like

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)

#8 King Mir   Members   -  Reputation: 1968

Like
0Likes
Like

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,

#9 ColinDuquesnoy   Members   -  Reputation: 1114

Like
0Likes
Like

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.


#10 King Mir   Members   -  Reputation: 1968

Like
0Likes
Like

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.

#11 ColinDuquesnoy   Members   -  Reputation: 1114

Like
1Likes
Like

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.


#12 King Mir   Members   -  Reputation: 1968

Like
0Likes
Like

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.



PARTNERS