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

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.

Related

Problem with accessing variable from function in another file

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

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 break out of a for loop using a function?

I'm running an if action defined in a function on a list of elements using a for loop. There is a secondary action within the first action. I want the for loop to stop once the action is successful the first time. Below is sample code to demonstrate:
my_list = [99, 101, 200, 5, 10, 20, 40]
def action(x):
if x >= 100:
print('It is finished')
over_100 = True
return over_100
def action2(x):
x += 1
action(x)
over_100 = False
for number in my_list:
action2(number)
if over_100:
break
I want the for loop to stop at the first instance of >=100. For example, it should add 1 to 99 (first element of the list) and then stop everything. Instead, it is printing "It is finished" 3x because it loops through the whole list.
You can make the function return a value and check the value in the loop. And you can use break to break out of the loop.
list_of_scopes = [scope1, scope2, scope3, etc.)
def action_function():
return 'TEST' in xxxxx
for scope in list_of_scopes:
found = action_function()
if found:
break
As of Python 3.8 you could even use the walrus operator which makes for more readable code:
for scope in list_of_scopes:
if found := action_function():
# optionally do something with `found`
break
A totally different approach to show what I meant in my comment on the question:
from contexlib import suppress
class StopProcessing(StopIteration):
pass
def action_function(param):
if 'TEST' in param:
print('TEST is found!')
raise StopProcessing
with suppress(StopProcessing):
for scope in list_of_scopes:
action_function()
I think you are looking for global.
Global tells your function's scope to not create a new variable over_100 but instead re-use an over_100 that was declared in a higher scope.
I do prefer the other answers that return a value instead of polluting global scope. Whatever works!
my_list = [99, 101, 200, 5, 10, 20, 40]
over_100 = False
def action(x):
global over_100
if x >= 100:
print('It is finished')
over_100 = True
def action2(x):
global over_100
x += 1
action(x)
if over_100:
return
# here is more work for action2 that you skip when over_100
for number in my_list:
action2(number)
if over_100:
break
Output:
It is finished
list_of_scopes = [scope1, scope2, scope3, etc.)
def action_function(param):
found = False
if 'TEST' in param:
print('TEST is found!')
found = True
return found
for scope in list_of_scopes:
result = action_function(scope) # or whatever parameter
if result:
break

How can I check if the current string and previous string in Python code?

In this code I want to compare the previous message with the current message. So I created a variable to save the previous message. I wanted to create it as a static variable then manipulate it inside the code. but the outside the x function if I declare the variable it shows an error.
flag = 1
previousMessage = "abc"
def x():
do_something
currentMessage = m #got a string from code
if(currentMessage==previousMessage):
#shows error in flag and previousMessgae
#says create parameter of previousMessage and flag
flag=0
return
else:
do_something
previousNews=currentNews
flag=1
return
def call():
while True:
if(flag==1)
x()
time.sleep(60)
elsif(flag==0)
time.sleep(60) **strong text**
call()
Not sure if this is what you need. Try adding global before flag and previousMessage to make that variable a global variable.

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