So I am trying to declare the variable "checks" as a global variable because I get the following issue:
File "C:\Python27\Projects\Automatic Installer\autoinstall.py", line 11, in installFunc
if checks[0] == 1:
NameError: global name 'checks' is not defined
Here's my code, I've tried to add global checks to both the main body of the program as well as the installFunc function. Is there another location I should be adding it/some other way to indicate that checks should contain the information in the program?
import urllib
import subprocess
from Tkinter import *
global checks
def installFunc():
global checks
subprocess.call("md c:\MGInstall", shell=True)
subprocess.call (u"net use w: \\it01\files")
if checks[0] == 1:
subprocess.call(u"w:\\software\\snagitup.exe")
if checks[1] == 1:
subprocess.call(u"w:\\software\\camtasia.exe")
if checks[2] == 1:
urllib.urlretrieve(u"SUPERLONGURLLOLOLOL", u"c:\\MGinstall\\gotomeeting.exe")
subprocess.call (u"c:\\MGinstall\\gotomeeting.exe")
urllib.urlretrieve(u"http://ninite.com/.net-7zip-air-chrome-cutepdf-dropbox-essentials-firefox-flash-flashie-java-klitecodecs-quicktime-reader-safari-shockwave-silverlight-vlc/ninite.exe", u"c:\\MGinstall\\MGinstall.exe")
subprocess.call (u"c:\\MGinstall\\MGinstall.exe")
subprocess.call (u"w:\\printers\\installer\\printer.exe")
app = Tk()
w = Label(app, text="CompanyName IT Automatic Installer")
w.pack()
text = ["Snagit", "Camtasia", "GotoMeeting"]
variables = []
for name in text:
variables.append(IntVar())
Checkbutton(text=name, variable=variables[-1]).pack()
b = Button(text="OK", command=installFunc)
b.pack()
app.mainloop()
checks = [variable.get() for variable in variables]
I think this is because checks gets set after the mainloop (the last line of the posted code). the function installFunc gets called from the mainloop via a button press, but checks hasn't been defined yet.
Using the global data in this case isn't a good idea anyway. You should probably do something like:
def installFunc(checks):
...
checks = [variable.get() for variable in variables]
b = Button(text="OK", command=lambda : installFunc(checks))
Or, even better, wrap all this up in a class... that way you can do:
self.b=Button(..., command=self.installFunc)
Replace the first 'global checks' (the one at the global level) with 'global = ...', initializing it appropriately. Using 'global' is really relevant only within a function/method. Per the Python docs: The global statement is a declaration which holds for the entire current code block. It means that the listed identifiers are to be interpreted as globals. It would be impossible to assign to a global variable without global, although free variables may refer to globals without being declared global. You may want to read this as well - has lots of relevant info: Using global variables in a function other than the one that created them
The problem is not the first 'global checks'. What causes the error is that checks is accessed before it is initialized.
You must initialize checks before calling the main loop of the application.
First of all, Python is not PHP.
You need to use keyword global if an only if, you're going to assign to global variable within scope of a function.
global checks at top level makes no sense at all, and more importantly does not define that variable.
global checks in your installFunc() does not make sense, as you do not assign anything to that variable, in fact you don't even modify it.
In Python variables from outer scope are visible in local scope, unless of course you try to assign something, which would be interpreted as redefining that variable within local scope.
Problem with your code is that you only define checks after exiting main loop. Correct code would look like this
import urllib
import subprocess
from Tkinter import *
#no global definition here...
def installFunc():
#no global definition here...
subprocess.call("md c:\MGInstall", shell=True)
...
...
#define checks before starting main loop
checks = [variable.get() for variable in variables]
app.mainloop()
Related
What to use instead of global variables in python? The value of the global variable changes during runtime.
I have a file: mygui.py where global variables are used and their value is changed during runtime.
mygui.py
#gui with tkinter
import globals
globals.VAR1 = True
globals.VAR2 = 123
# some gui stuff happens
globals.VAR1 = False
globals.VAR2 = 3212231
# another gui stuff happens based on new values
globals.py
globals.VAR1 = False
globals.VAR2 = 111
How do I implement this without needing of globals, so without needing the file globals.py? I am using the global values during runtime and the app is dependent on these globals. So I need to store the values somewhere and have them available all the time.
You can use environment variables, with os.environ that is a dictionary.Python doc
Similar questions to this have been asked and answered but none dealt with this specific question.
global EXAMPLE_GLOBAL
EXAMPLE_GLOBAL = True
def Setup():
if EXAMPLE_GLOBAL:
try:
#Doing some file io here
except:
global EXAMPLE_GLOBAL
EXAMPLE_GLOBAL = False
When running this code (Not this code exactly, this is just stripped down to the basic logic.) I get:
SyntaxWarning: name 'EXAMPLE_GLOBAL' is used prior to global declaration
global EXAMPLE_GLOBAL
I was under the impression that to change the value of a global variable you must first specify that you were referencing the global variable when you went to a new scope. Do I need the second 'global EXAMPLE_GLOBAL' in order to make the change to the global or is using the same identifier enough?
I was under the impression that to change the value of a global variable you must first specify that you were referencing the global variable when you went to a new scope
Yes, that's right. But conventionally, the global statement should go at the opening of that scope. In other words, put it at the top of your function.
EXAMPLE_GLOBAL = True
def Setup():
global EXAMPLE_GLOBAL
if EXAMPLE_GLOBAL:
try:
#Doing some file io here
except:
EXAMPLE_GLOBAL = False
The documentation explicitly recommends against referring to a name in a block before using it in a global statement:
Names listed in a global statement must not be used in the same code block textually preceding that global statement.
In CPython, violating this principle only produces a warning instead of an error because the parser ignores the specific position of the global directive within a block, but that's an implementation detail and could change in the future.
(Also note that you don't need the global statement on the first line. Every name at the top-level scope is already effectively global in that scope.)
I cannot quite find a good description on how import works when importing your own files.
I was having trouble importing a file with a global variable and managed to get it to work when I put the global variable just before the files main function.
Can someone explain why it works this way?
A quick run down on how import actually works.
It did not work when I did this (pseudocode):
file1:
import file2
file2.main()
file2:
main():
glob_var = 0
def add():
global glob_var
glob_var += 1
add()
But worked if I put the variable first like this:
file1:
import file2
file2.main()
file2:
glob_var = 0
main():
def add():
global glob_var
glob_var += 1
add()
'main' is just a method. Variable inside a method is local by definition. Thats why 2nd way is working.
The reason it didn't work is because you are declaring the global variable inside of main. (you did miss the colon after definition of main which makes it confusing but looking at the indentation I suppose it's a definition). Global variables have to be defined outside the scope of any local function. This is a case of nested function definition.
You can do without global variables as well if that's what you are looking for. If however you want to use the variable defined in main inside a nested function then you can do the following:
In python 3 there is a way to get this thing done however using the nonlocal keyword
def main():
var = 10
def nested_fun():
nonlocal var
var = var + 1
As you see we do not need a global variable here.
Edit: In case of python 2 this does not work. However you can use a list in the main and modify that list inside nested function.
def main():
var = [10]
def nested_fun():
nonlocal var
var[0] = var[0] + 1
If I understand the question correctly, it's regarding the global variable and have nothing to do with importing.
If you want to define a global variable, it has to be defined in module level. The main function is not the global scope, that's why the first code does not work as expected. By moving the variable declaration outside of main, it would be defined in global scope, so the add method can access it using as a global variable.
I think we have to begin with what global statement means. From the docs:
It means that the listed identifiers are to be interpreted as globals.
The important point is it's only about interpretation, i.e. global does not create anything. This is the reason, why your first example does not work. You are trying to add +1 to something not existing. OTOH, global_var = 100 would work there and it would create a new global variable.
All I want is to assign some initial value to the variable 'extra_devices' and if the user specifies some value to this variable at the run time, the default value gets replaced with the user's specified value. I am adding a minimal code snippet to show what I am doing.
While running this program, if I do not specify 'extra_devices', the program fails to run saying 'UnboundLocalError: local variable 'extra_devices' referenced before assignment', but I fail to understand the reason since I have already assigned the value to it. However, the program works fine if I specify 'extra_devices' at runtime. Anyone got any reasoning for this behavior?
Notice variable 'abc' prints fine in main().
#/usr/bin/python
import argparse
extra_devices=10
abc = 1
def main():
parser = argparse.ArgumentParser(description='')
parser.add_argument('-extra_devices','--extra_devices',help='extra_devices',required=False)
args = parser.parse_args()
if args.extra_devices is not None: extra_devices = args.extra_devices
print "abc="+str(abc)
print "extra_devices = "+str(extra_devices)
if __name__ == '__main__':
main()
Add one line in the function:
global extra_devices
Then you can write to the global variable in the function.
The reason is because you may change that variable in the function, and the interpreter will define it as a local variable instead of global variable for protecting the global variable, except you assign that variable is a global variable.
Update:
Add the reason.
How can I assign a function argument to a global variable with the exact same name?
Note:
I can't do self.myVariable = myVariable because my function is not inside of a class.
When write the following code, I get an error saying that "argument is both local and global."
myVar = 1
def myFunction(myVar):
global myVar
Is this impossible? and if so is it uncommon in other languages? Coming from java I'm used to this.myVar = myVar
Edit I already know that I can rename the variable. That's the easy way out.
Best solution: refactor your code. Rename something, or use an object with object properties instead of a global variable.
Alternative, hacky solution: modify the global variable dict directly:
my_var = 1
def my_function(my_var):
globals()['my_var'] = my_var
The answer is to trick Python into doing it. In your code:
myVar = 1
def myFunction(myVar):
global myVar
myFunction is never run (you never call it). So, the script never gets to the global myVar point. Yet, Python still blows up for some reason. I believe that that is because it has been told "Don't allow this". Regardless, you can trick it into doing what you want. One way that hasn't been suggested is to use a simple function in myFunction:
myVar = 1
def myFunction(myVar):
def trick(arg):
global myVar
myVar = arg
trick(myVar)
print myVar # Comes back with 1
myFunction(22)
print myVar # Comes back with 22
May not be on one line, but you don't have to import anything and it is easier to read.
The best (and fastest) thing to do would be to take the easy way out and rename the variable(s). But if you insist, you could get around the naming conflict with this:
import sys
_global = sys.modules[__name__]
# or _globals = sys.modules[__name__].__dict__
myVar = 1
def myFunction(myVar):
_global.myVar = myVar # or _globals['myVar'] = myVar
print myVar # 1
myFunction(42)
print myVar # 42
Explanation:
Within a module, the module’s name (as a string) is available as the value of the global variable__name__. The namesys.modulesrefers to a dictionary that maps module names to modules which have already been loaded. IfmyFunction()is running, its module has been loaded, so at that timesys.modules[__name__]is the module it was defined within. Since the global variableMyVaris also defined in the module, it can be accessed using sys.modules[__name__].myVar. (To make its usage similar to java, you could name itthis-- but personally I think_globalis a better.)
In addition, since a module’s read-only__dict__attribute is its namespace -- aka the global namespace -- represented as a dictionary object,sys.modules[__name__].__dict__ is another valid way to refer to it.
Note that in either case, new global variables will be created if assignments to non-existent names are made -- just like they would be with the global keyword.