Solved

capture key press

Posted on 2010-11-11
9
1,258 Views
Last Modified: 2012-05-10
Using Python3 (console mode).

I am trying to capture key press (restrict to certain digits and charaters) - non-allows characters presses not displayed otherwise see a text string appear on screen.

New to Python -- advise much appreciated
import msvcrt        

def doKeyEvent(key):
    if key == '\x00' or key == '\xe0':    # non ASCII
       key = msvcrt.getch()
    print (ord(key),)

def doQuitEvent(key):
    raise SystemExit


def keyTest1() :


    ky = msvcrt.getch()
    length = len(ky)
    if length != 0:         
        if ky == " ":
            doQuitEvent(ky)
        else: 
            doKeyEvent(ky)

Open in new window

0
Comment
Question by:amillyard
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 3
9 Comments
 
LVL 29

Expert Comment

by:pepr
ID: 34118512
Try the following snippet to see, what is returned.  Now, the important thing is to understand that there is a strict difference between strings and bytes in Python3.  The msvcrt.getch() returns the bytes type (literals having b in front of the first quotation mark).  This way, you have to convert the bytes explicitly to get the string.  Strings in Python3 are always in Unicode.  This also means that you have to tell the encoding for the conversion.

I do recommend to read the Strings chapter (http://diveintopython3.org/strings.html) from Dive Into Python 3 by Mark Pilgrim (http://diveintopython3.org/), namely the section Strings vs. Bytes (http://diveintopython3.org/strings.html#byte-arrays).
import msvcrt        

k = None          # init
while k != b' ':  # press space to leave the loop
    k = msvcrt.getch()
    print(repr(k))

Open in new window

0
 

Author Comment

by:amillyard
ID: 34119051
thanks for the feedback.

when I apply the above scripting... the   b'\xff'  constantly streams upwards.

what I am hoping to achieve is text entry on a single line ... any non-allowed character  (from a list eventually) simply does not get added to the input (ignored).

at the moment I cannot break unless using Ctrl-C



b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
Traceback (most recent call last):
  File "C:\Users\Administrator\Desktop\ass1.py", line 357, in <module>
    elif len(line)==1 and "1"<=line<="9" : exlist[int(line)]()
  File "C:\Users\Administrator\Desktop\ass1.py", line 248, in ex8
    print(repr(k))
KeyboardInterrupt
>>> 
0
 
LVL 29

Expert Comment

by:pepr
ID: 34119113
Can you show your code from around the line 248 in ass1.py?
0
Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 29

Expert Comment

by:pepr
ID: 34119114
... and around 357
0
 

Author Comment

by:amillyard
ID: 34119120
there are basically just a bunch of functions ... the break was the ctrl-c to force the stop... otherwise -the scripting loops on itself (the above scripting)
0
 
LVL 29

Expert Comment

by:pepr
ID: 34119156
I am just curious where the b'\xff' came from.
0
 

Author Comment

by:amillyard
ID: 34119168
this is the only scripting in that section - a loop to select different functions to test various routines as attached
# do not modify anything beneath this line
exlist = [None, ex1, ex2, ex3, ex4, ex5, ex6, ex7, ex8, ex9]
running = True
while running :
    line = input("\nSelect option (0 to quit): ")
    if line == "0" : running = False
    elif line == "10" : ex10()
    elif len(line)==1 and "1"<=line<="9" : exlist[int(line)]()
    else : print("Invalid input - try again")

Open in new window

0
 
LVL 29

Expert Comment

by:pepr
ID: 34119627
I am afraid you cannot combine the standard input() function and the msvcrt.getch() together.  I may be wrong but you need to write your own implementation of the input() -- say myInput().  Try the code below to discuss about.  It uses getch() to get the characters of the keys and collects them in the list of single-char strings.  However, it is rather simplistic as it works only with ASCII characters.  Try to press the arrow key or some accented character and you will know what I mean.  On the other hand, there are places in the code where the tests could be added to solve the situations.
import msvcrt        

k = None      # init
lst = []
while k != b'\r':
    k = msvcrt.getch()
    if k != b'\r':
       msvcrt.putch(k)
       lst.append(k.decode('ascii'))

msvcrt.putch(b'\n') 
    
print(repr(''.join(lst)))

Open in new window

0
 
LVL 29

Accepted Solution

by:
pepr earned 500 total points
ID: 34119888
Try the following myInput() function.  You may want to implement it better so that it could run also on non-Windows OS.
import msvcrt
import sys


def myInput(prompt):
    sys.stdout.write(prompt + ' ')
    sys.stdout.flush()
    k = None                               # init the key value
    lst = []                               # list of accepted chars
    while k != b'\r':
        k = msvcrt.getch()                 # get the key 
        if k == b'\xe0':                   # arrow key sequence?
            x = msvcrt.getch()             # the arrow identifier
            sys.stdout.write('\a')         # beep
            sys.stdout.flush()
        
        # Filter out the unwanted characters here.
        # Possibly beep if you do not like it -- here, do not allow 'a'.
        elif k == b'a':
            sys.stdout.write('\a')
            sys.stdout.flush()
            
        elif k != b'\r':         
            c = k.decode(sys.stdin.encoding) # to be displayed
            sys.stdout.write(c)
            sys.stdout.flush()
            lst.append(c)

    sys.stdout.write('\n')
    return ''.join(lst)
    
    
print(myInput('my prompt:'))    
print(myInput("try to enter 'a' char:"))    
print(myInput('try to press the arrow key:'))

Open in new window

0

Featured Post

Secure Your Active Directory - April 20, 2017

Active Directory plays a critical role in your company’s IT infrastructure and keeping it secure in today’s hacker-infested world is a must.
Microsoft published 300+ pages of guidance, but who has the time, money, and resources to implement? Register now to find an easier way.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Merge XML files using a unique key? 8 116
linux crontab output 3 80
Ptyhon Dex.txt how to use this regex for this python script? 40 100
Python to .bat or Powershell 2 28
This article will show the steps for installing Python on Ubuntu Operating System. I have created a virtual machine with Ubuntu Operating system 8.10 and this installing process also works with upgraded version of Ubuntu OS. For installing Py…
Here I am using Python IDLE(GUI) to write a simple program and save it, so that we can just execute it in future. Because when we write any program and exit from Python then program that we have written will be lost. So for not losing our program we…
Learn the basics of strings in Python: declaration, operations, indices, and slicing. Strings are declared with quotations; for example: s = "string": Strings are immutable.: Strings may be concatenated or multiplied using the addition and multiplic…
Learn the basics of if, else, and elif statements in Python 2.7. Use "if" statements to test a specified condition.: The structure of an if statement is as follows: (CODE) Use "else" statements to allow the execution of an alternative, if the …

756 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question