I'm trying to record the keyboard input to a pseudoterminal in python using the pty module in python's standard library. I'm having some difficulty capturing only the keyboard input. While I can easily record the stdout using the callback listed here (in the module documentation), I can't figure out how to get the keyboard input. Should I be using something like termios in conjunction with pty?
If this is possible in another language like C, please also tell!
Related
TL;DR, I'm trying to make a python-only single-module platform-nonspecific non-blocking keypress detector that works in IDLE.
Good luck.
So say I'm running a loop, in IDLE, for an arbitrary amount of time. I want a way to get user input without blocking the loop, on any system I want.
Example:
import keyboard #(is one module in same directory)(Mac, Windows, Linux, who knows?)
teststring = ''
while True:
if keyboard.isDown('a'):
teststring += 'a'
if keyboard.isDown('enter'):
if 'a' in testring:
break
... (neural network or whatever continues)
To put it a different way, I'm trying to make a universal event listener that works in IDLE. If one already exists, do let me know, but I have done some research and none work in one easy-to-use module.
Note:
You don't have to write this, I just want to know what pre-installed Python modules you would use to do this and a general idea of how to go about it.
I am trying to make an application that redoes my exact movements on keyboard on a certain process, so I am attempting to register my keyboard strokes time-stamped, I tried to do it using msvcrt or pygame, however they both require keys to be entered to the command prompt itself, else it wont detect it.
Is it possible to create a time-stamped "keylogger" using PYTHON
P.S: I just want to learn more about python scripting.
this is the code i tried:
import msvcrt
import time
import datetime
while True:
char = msvcrt.getch()
print char
print datetime.datetime.now().time()
What you've written is a program that captures inputs to itself. What you need, at least for Windows, are global input hooks. This will allow your application to capture all input to the machine.
Take a look at the following resources:
Windows Hooks Overview
Python for Windows Extensions
PyHook, a Python wrapper for global input hooks
As a php programmer (of sorts) very new to os and command line processes, I'm surprised that within python, everything a user inputs during the course of interacting with a program seems to be buffered, waiting to pour out at the first use of raw_input (for example).
Found some code to call prior to raw_input which seems to "solve" the problem on osX, although supposedly it is providing access to windows capabilities:
class FlushInput(object):
def flush_input(self):
try:
import msvcrt
while msvcrt.kbhit():
msvcrt.getch()
except ImportError:
import sys, termios
termios.tcflush(sys.stdin, termios.TCIOFLUSH)
Am I understanding correctly that stdin and stdout, stderr methods will vary between OSs?
I imagine that maybe a framework like Django has built-in methods that simplify the interactivity, but does it basically take a few lines of code just to tell python "don't accept any input until it's invited?"
Ahhh. If I'm understanding this correctly (and I'm sure the understanding needs much refining), the answer is that yes, stdin, stdout, stderr, "Standard" input, output and error streams and their handling may vary from (operating) system to system, because they are products of the OS and NOT any particular programming language.
The expectation that "telling python to ignore stdin until input is requested" would be automatic stems from an thinking of the "terminal" as if it were a typewriter. Where the goal of a typewriter is to record strings of information in a human-readable format, the goal of a terminal is to transmit information which will ultimately be converted to a machine-readable format, and to return human-readable responses.
What most of us coming to computing currently think of as a "terminal" is actually a virtual recreation of a physical machine known as a terminal which used to be the method by which data would be input to and read from a computer processor, right? And a text-editor an application that creates a virtual type-writer out of the keyboard, monitor and processing capabilities of the operating system and included libraries of programs.
An application like the mac OS terminal or even the tty we use to engage with another server via and ssh connection is actually creating a virtual terminal through which we can engage with the processor, but sending information to stdin and receiving from stdout and strerr. When the letters we type appear in the terminal screen, it is because it is being "echoed" back into the terminal window.
So there's no reason to expect that the relationship between python or any other language and a terminal, would by default block the input stream coming from a terminal.
The above code uses pythons exception handling to provide two alternative ways of flushing the input stream prior to some activity on behalf of the program. On OSX platform the code:
import sys, termios
termios.tcflush(sys.stdin, termios.TCIOFLUSH)
imports the system so we can have access to stdin, and termios, which is python's module for managing the POSIX (LINUX, UNIX) application which actually manages TWO virtual terminals - one between itself and the user, and another between itself and the operating system. tcflush appears to be a function that accepts at least two parameters - the first being WHICH stream to flush - the file descriptor (fd), and the second being the queue to flush. I'm not sure what the difference is between the file descriptor and queue is in this case, except that maybe the fd contains data that hasn't yet been added to the queue and the queue contains data that is no longer contained in the fd.
msvcrt is the python module for interacting with (managing) whatever Windows version of a terminal is, and I guess msvcrt.kbhit() and msvcrt.getch() are functions for flushing it's input queue.
The UNIX and Windows calls of the function could be swapped so that rather than saying, try: doing it the windows way and if an ImportError is raised to it the UNIX was, we try: the UNIX way first:
class FlushInput(object):
def flush_input(self):
try:
import sys, termios
termios.tcflush(sys.stdin, termios.TCIOFLUSH)
except ImportError:
import msvcrt
while msvcrt.kbhit():
msvcrt.getch()
Here's a termios introduction that helped clarify the process.
There is some way to get the device path of a mouse and keyboard using Xlib based in a looping with XNextEvent? I need to know what /dev/input/event* generates a event specific like mouse press and keyboard key F1 press.
I'm using evdev for input devices in Xorg, I searched documentation and cannot find a way.
I accept too suggestion of some app that I can use to identify input device based in events like mouse press and keyboard press.
Thanks.
Edit: If there is a way to make this using another lib, preferable one with bindings for python, please let me know.
I realize that Xlib do not have a method to get the file descriptor of the input devices, so I figured out another way to resolve this case, is not ready yet, but apparently is the best way to follow, just posting here for someone with the same problem.
I'm using the module python-evdev (installed with pip in ubuntu), with this module I can monitor the devices is /dev/input/event*, so I just need to start a thread for each device that I previous identified which is a mouse or keyboard (using the module evdev and checking if device have "capabilities(verbose=True)" with event codes like ecodes.KEY_F1 and ecodes.BTN_MOUSE), and when a event occur, write to a shared variable, that I should monitor.
For the graphic interface running in Xorg, without Windows Managers, I using python-glade2, works like a charm, I run a Xorg with python-glade2 app using xinit.
Is there a way to programmatically interrupt Python's raw_input? Specifically, I would like to present a prompt to the user, but also listen on a socket descriptor (using select, for instance) and interrupt the prompt, output something, and redisplay the prompt if data comes in on the socket.
The reason for using raw_input rather than simply doing select on sys.stdin is that I would like to use the readline module to provide line editing functionality for the prompt.
As far as I know... "Sort of".
raw_input is blocking so the only way I can think of is spawning a subprocess/thread to retrieve the input, and then simply communicate with the thread/subprocess. It's a pretty dirty hack (at least it seems that way to me), but it should work cross platform. The other alternative, of course, is to use either the curses module on linux or get this one for windows.