Problem with accessing variable from function in another file - python

I need to get a variable declared in a function in another file.
Requirement is that I can't call the variable from setvar() function.
set.py:
def setvar():
global x
x = 100
def getvar():
return x
if __name__ == '__main__':
setvar()
getvar()
get.py:
import set
y = set.getvar()
print(y)
Error:
NameError: name 'x' is not defined
Why is x not defined? When I print it in getvar, x is defined.
How can I change it to get it work?

Why is x not defined?
The reason is because of your line:
if __name__ == '__main__':
As you know, that line means to only run the code within the if statement if the program is being run directly, rather than being imported into another program. As you are only importing the set.py program into the get.py program, the setvar() function never got called, hence the x variable never got defined.
Requirement is that I can't call the variable from setvar function.
That's not a problem! All you'll need to do is call the setvar() function outside of the if __name__ == '__main__': block once, and the problem would be fixed:
set.py:
def setvar():
global x
x = 100
def getvar():
return x
setvar()
if __name__ == '__main__':
getvar()
get.py:
import set
y = set.getvar()
print(y)
Output:
100

Related

Python3 method not callable due to UnboundLocalError

Take into account the following code:
def main():
print('Calling methodA()')
methodA()
print('Calling methodB(True)')
methodB(True)
print('Calling methodB(False)')
try:
methodB(False)
except UnboundLocalError as error:
print(f'--> "UnboundLocalError" raised: {error}')
def methodA():
print('Running methodA()')
print('"method_original" in globals(): ' + str('method_original' in globals()))
method_original()
def methodB(patch_function):
print(f'Running methodB({patch_function})')
print('"method_original" in globals(): ' + str('method_original' in globals()))
if patch_function:
method_original=method_patched
method_original()
def method_original():
print('Running method_original()')
def method_patched():
print('Running method_patched()')
if __name__ == '__main__':
main()
It produces the following output:
Calling methodA()
Running methodA()
"method_original" in globals(): True
Running method_original()
Calling methodB(True)
Running methodB(True)
"method_original" in globals(): True
Running method_patched()
Calling methodA(False)
Running methodB(False)
"method_original" in globals(): True
--> "UnboundLocalError" raised: local variable 'method_original' referenced before assignment
Which makes no sense because "method_original" is in globals(). This error can be fixed simply adding global method_original at the beginning of the methodB() but in some cases we have a lot of functions and it could be a pain in the ass to put all of them at the beginning of every method.
Are there any rules to avoid this behavior?
//BR!
Let me explain it in a simpler example :
def fn(a):
if a % 2 == 0:
x = a
return x
print(fn(10)) # Fine
print(fn(9)) # UnboundLocalError: local variable 'x' referenced before assignment
In compile time, when interpreter reaches the function, it sees that there is an assignment to x, so it marks x as a "local" variable. Then in "runtime" interpreter tries to find it only in local namespace ! On the other hand, x is only defined, if a is even.
It doesn't matter if it presents in global namespace, now I want to add a global variable named x, to my example:
def fn(a):
if a % 2 == 0:
x = a
return x
x = 50
print(fn(10)) # Fine
print(fn(9)) # UnboundLocalError: local variable 'x' referenced before assignment
Nothing changed. Interpreter still tries to find x inside the function in local namespace.
Same thing happened in your example.
This is to show which variables are "local":
def fn(a):
if a % 2 == 0:
x = a
return x
print(fn.__code__.co_varnames)
co_varnames is a tuple containing the names of the local variables
(starting with the argument names)
Solution:
Either use global (which I see you don't like) , or do not do assignment inside the function, for example change your methodB to :
def methodB(patch_function):
print(f'Running methodB({patch_function})')
print('"method_original" in globals(): ' + str('method_original' in globals()))
if patch_function:
method_patched()
else:
method_original()

How to access the nonlocal variable in enclosing function from inner function if inner function already has its variable with the same name Python

I need to find the way to reference variable x = "Nonlocal" from inner_function_nonlocal(). Probably, the way how I referenced the x = "Global": globals()['x'], but I need your help with that one, please!
Please note: I can NOT comment or delete x = "Local" in order to write nonlocal x instead of it.
x = "Global"
def enclosing_funcion():
x = "Nonlocal"
def inner_function_global():
x = "Local"
print(globals()['x']) # Call the global a
def inner_function_nonlocal():
x = "Local" # <- This line can NOT be commented!!!
print(_?_?_?_?_) # <- What should I specify here in order to print x which is nonlocal?
inner_function_global()
inner_function_nonlocal()
if __name__ == '__main__':
enclosing_funcion()
output should be:
Global (this is already achieved)
Nonlocal (need help to get this one)
You can add a method to get at the Nonlocal value:
x = "Global"
def enclosing_funcion():
x = "Nonlocal"
def non_local():
return x
def inner_function_global():
x = "Local"
print(globals()['x']) # Call the global a
def inner_function_nonlocal():
x = "Local" # <- This line can NOT be commented!!!
print(non_local()) # <- What should I specify here in order to print x which is nonlocal?
inner_function_global()
inner_function_nonlocal()
if __name__ == '__main__':
enclosing_funcion()
Result:
Global
Nonlocal

Local variable not declared - cannot be fixed with any current stack solutions

I understand this is a question asked several times on here, but even after viewing and attempting to use all solutions on this site none fix my problem. Here is my code:
def trackMouse():
global x, y
x = 0
y = 0
x_max = 1000
y_max = 1000
keyboardEvent = evdev.InputDevice('/dev/input/event0')
mouseEvent = evdev.InputDevice('/dev/input/event1')
async def print_events(device):
async for event in device.async_read_loop():
if event.type == ecodes.EV_REL:
if event.code == ecodes.REL_X:
print("REL_X")
x += 1
if event.code == ecodes.REL_Y:
print("REL_Y")
y += 1
if event.type == ecodes.EV_KEY:
c = categorize(event)
if c.keystate == c.key_down:
print(c.keycode)
for device in keyboardEvent, mouseEvent:
asyncio.ensure_future(print_events(device))
loop = asyncio.get_event_loop()
loop.run_forever()
the error i get when running this loop is:
Task exception was never retrieved
future: .print_events() done, defined at etho.py:113> exception=UnboundLocalError("local variable 'a' referenced before assignment",)>
Traceback (most recent call last):
File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
result = coro.send(None)
File "etho.py", line 124, in print_events
if x += 1:
UnboundLocalError: local variable 'x' referenced before assignment
no matter where i assign the variable or declare it it will throw an error when i try to use it in an if statement or add to it, but not when i just set it equal to a number. I think it has something to do with the weird loop it is in.
print_events is treating x and y as local to itself, since they're modified inside the function and are not declared global inside the function. Since you want to modify them, you need to add declare them global inside print_events:
async def print_events(device):
global x, y
async for event in device.async_read_loop():
...
Note that passing them as arguments won't work since you want to modify them within the function and access the modified values outside the function.

How to call another function (temperature) as main function

I was typing a sample code. Where I defined temperature as the main function, but I was unable to run it. It closed automatically without any input prompt.
def temperature():
number = input('Enter what you want\n')
values = number.split(' ')
temperature = values[0]
unitin = values[1]
unitout = values[-1]
print(temperature, 'this', unitin, 'is', unitout, 'working') # this is working is a test statemment i was unsure
print('This is a test function', number)
def main():
temperature()
if __name__ == "__main__":
main()
this is the part of the code that ran. But as soon as I tried to change just the name of the main function it stopped working. I am not sure, does it only take the name "main"?
def readinput():
input_string = input('Enter what you want\n')
values = input_string.split(' ')
temperature = values[0]
unitin = values[1]
unitout = values[-1]
print(temperature, 'this', unitin, 'is', unitout, 'working')
print('This is a test function', input_string)
def temperature_converter():
readinput()
if __name__ == "__temperature_converter__":
temperature_converter()
This is the code that did not work. thank you.
If you run your code on its own, the variable __name__ is automatically set to "__main__" by the interpreter. That does not have anything to do with your functions name. Have a look at What does if __name__ == "__main__": do?
This should work:
if __name__ == "__main__":
temperature_converter()
You're confusing the contents of the special variable __name__ that contains string '__main__' in case when the module is run by itself (as opposed to imported by another module) with the function main() -- these are totally unrelated things, and when you change the name of the function main() to whatever else you like, leave the string __main__ alone, as it is.
Or you may remove the line starting with if __name__ == completely, it should work without is as well.

Pygame beginner programs, screen undefined

AMOUNT = 1
x = 175
y = 175
def main():
screen = pygame.display.set_mode((600,600))
screen.fill( (251,251,251) )
BoxAmountCalc(humaninput)
DrawBoxCalc()
pygame.display.flip()
while True:
for event in pygame.event.get():
if event.type == QUIT:
return
def BoxAmountCalc(x):
x = (2**humaninput) * (2**humaninput)
size = 600/x
return size
def DrawBoxCalc():
while True:
pygame.draw.rect(screen,(0,0,0), (x,y,size,size))
AMOUNT += 1
x = x + size
x = y + size
pygame.display.flip()
if AMOUNT > humaninput:
break
I've left out a few parts of the code, some of the variable definitions, but when I try to run this code it gives me an error saying that "screen" is not defined.
Is this because I need it to be defined as a parameter for the function and then pass it into the function, or am I missing something completely here?
Thank you for looking, I'm sorry for a very beginner question.
Is this because I need it to be defined as a parameter for the
function and then pass it into the function.
Yes. Once a function finishes executing, the variables created therein are destroyed. Here is an example:
def go():
x = 10
go()
print(x)
--output:--
Traceback (most recent call last):
File "1.py", line 5, in <module>
print(x)
NameError: name 'x' is not defined
Same thing here:
def go():
x = 10
def stay():
print(x)
go()
stay()
--output:--
File "1.py", line 9, in <module>
stay()
File "1.py", line 6, in stay
print(x)
NameError: name 'x' is not defined
But:
x = 10
def go():
print(x)
go()
--output:--
10
And better:
def go(z):
print(z)
x = 10
go(x)
--output:--
10
Try to keep your functions self contained, which means they should accept some input and produce some output without using variables outside the function.
In your code, you can do:
DrawBoxCalc(screen) and def DrawBoxCalc(screen):
but you also have an issue with humaninput. I would try to define DrawBoxCalc as DrawBoxCalc(humaninput, screen), and call it with both args. That means you will have to define main as main(humaninput).
Also, function names should start with a lower case letter, and python uses what is called snake_case for lower case names, so draw_box_calc, and class names should start with a capital letter and they can use camel case: class MyBox.

Categories