Running a function in Python every time any key is pressed? - python

First off, forgive me, because I'm incredibly new at this Python thing (I'm really an HTML/CSS kind of guy, but I'm trying to branch out). This is probably an elementary sort of question, but we all have to start somewhere, right?
I'm putting together a very basic Python program that will select a random letter from a string of letters and print it out every time someone hits the any key. The whole thing is pretty simple, and currently returns a random letter, but doesn't wait for a keypress to do so, and stops after completing the function runs once.
import random
letterlist = 'abcd'
def random_letter(letters):
print ('Press enter for a random letter...')
print random.choice(letters)
random_letter(letterlist)
Output should look like this:
Press enter for a random letter.
'b'
Press enter for a random letter.
(and so on...)
It's clear that whatever I need to do ought to fall inside of random_letter someplace. I've been googling around and have found lots of references to raw_input and mvscrt, but I'm not entirely sure what I need. It's entirely possible that I'm just asking the question wrong.
I'm assuming assuming that I need some sort of loop going on to keep this running indefinitely.
Thanks in advance!

For starters, you need a loop somewhere to continue prompting the user. You also need some sort of exit condition for the loop. This loop can be inside the function like so:
def random_letter(letters):
while True:
x = raw_input('Press enter for a random letter...')
if x == 'done':
break
print random.choice(letters)
random_letter('abcdef')
Notice that inside the loop we use raw_input to prompt the user to type something, anything, then press enter. When the user types done and hits enter, we break out of the loop using break.
An alternative would be to wrap your existing function in a loop and take care of the prompting outside the function.
def random_letter(letters):
print random.choice(letters)
while True:
x = raw_input('Press enter for a random letter...')
if x == 'done':
break
random_letter('abcdef')

If you don't have to use a loop, and thinking of capturing keyboard events, then there are no cross-platform ways of doing it: Is there a cross-platform python low-level API to capture or generate keyboard events?
For Windows, there is pyHook: http://pyhook.wiki.sourceforge.net/
You can look into the code of pyKeyLogger: http://pykeylogger.wiki.sourceforge.net/
Or a dirty way, capture interrupts: Capture keyboardinterrupt in Python without try-except

Related

How to implement an asynchronous function in python 3

I'm very new to programming as a whole. Had some basic experience with C++ and HTML, like simple calculators and other really basic stuff(I started learning on my own a few months ago) and because of this I'm not even sure if I am posting this question correctly. Maybe it goes without saying but I am new to stackoverflow as well(My first post!), so I may do some things wrong here and I kindly ask for your comprehension. Any constructive criticism is more than welcome!
So here's my problem: I am trying to make a simple chatting program in Python 3, but here's the catch: I want to use python's asychronous capabilities to allow the user to terminate the program at any given time the esc key is pressed. I've looked into a few libraries already, such as pynput, asyncio, tornado and getch(). But no matter how I change my code I just can't seem to reach my goal here.
I made an async function called runalways() that's supposed to run during the entire duration of the program, parallel to the other functions. But it doesn't and I couldn't figure out why...
I'm sorry if I couldn't explain my issue properly. Some terms and concepts are still rather blurry to me, but hopefully it won't be so for long. I'll leave the code I have so far which does a good job implementing the chat function, but that's about it. The async bit is basically inexistent at this moment.
It would be really appreciated if someone could explain what I'm missing:
import time, asyncio
from msvcrt import getch
# Creates a chat-like effect
def typing(text):
for i in text:
print(i, end=" ")
time.sleep(0.1)
time.sleep(1.0)
# Terminates the program
def termination():
print("Program terminated")
time.sleep(0.5)
SystemExit
# Defines async function to read pressed keys and terminate if Esc is pressed
# (Not working)
async def runalways():
while True:
print(ord(getch()))
key = ord(getch())
if key == 27: # Esc
termination()
# Initialize chatting
def startChat():
typing("\nHello!\n")
typing("How are you?\n\n")
typing("Answer:\t")
x = input()
typing("\nAnyways, that isn't relevant right now.\n")
time.sleep(0.5)
typing("Can we get started?\n\n")
typing("Answer(Y/N):\t")
x = input()
# validates input
while (x != "Y") & (x != "N"):
typing("\nHey, don't go fooling around now. Keep it real! Try again.\n\n")
typing("Answer(Y/N):\t")
x = input()
if (x == "Y") | (x == "y"):
typing("\nThere you go! Now, let's go through the basics...\n\n")
termination()
elif (x == "N") | (x == "n"):
typing("\nSorry to hear that... See you next time, then!")
termination()
# Defines starter point for the program
def main():
runalways()
startChat()
main()
I will try my best to clarify any questions that may help the understanding of my issue. Thanks in advance!
You have two functions competing to grab the input. runalways wants to grab them with getch, while your main chat loop is trying with input. The two processes conflict; only one can consume each character. Whenever one thread grabs input, the other gets to claim the buffer for the next input.
Instead, you need to set up a single input channel that terminates immediately on ESC; otherwise, it echoes to the terminal and passes the character to the main loop (or buffers it until EOL appears).

Does python takes enter as an input?

I executed a program to input n space-separated integers as input, create a tuple, and the use hash() on them.
print(hash(tuple(map(int, input().split(" ")))))
I am using Pycharm IDLE.
While execution after entering the numbers and pressing I get the answer in one line in the following code:
print(input()==0 or hash(tuple(map(int,input().split()))))
But After I press enter in the following code, the pointer moves to the new line and then I have to press enter again.
My question is :
1) Why do I have to press enter twice in the second one.
2) Does Python takes enter as an input or as a null input.
A dry run would be clarify a lot of my doubts.
As others have already said, the reason you're having to press enter twice when running the code
print(input()==0 or hash(tuple(map(int,input().split()))))
is simply because you're calling the input function twice. This behavior can be reproduced with a simple example
>>> input(), input()
pressed enter once
pressed enter twice
('pressed enter once', 'pressed enter twice')
>>>
Since you only want to ask the user for input once, you need to save the result of the first call to input in a variable:
>>> var = input(); print(var == 0 or hash(tuple(map(int, var.split()))))
3527539
>>>
Also, as others have already said, I'm not really sure why you tried to write your code all on one line. Yes writing concise code is not a bad goal, so long as that code remains readable. Often times it's simply better (and in your case, necessary) to divide you code among multiple lines.

Looping a whole program in python using true and false statements

I have written a program but I do not know how to loop it. Help would be appreciated.
Here is the program I need help with.
There are two types of loops: indefinite (while) loops and definite (for) loops. If you want to loop your program a specific amount of times, then use the for loop:
for count in range(0, <number of repetitions minus one>):
# code
If you want to loop the program until the user enters "QUIT" or some other string, use this:
sentinel = input("Enter QUIT to exit or anything else to continue: ")
while sentinel.upper() != "QUIT":
# code
Here are some helpful links to tutorials:
http://www.learnpython.org/en/Loops
http://www.python-course.eu/python3_for_loop.php
http://anh.cs.luc.edu/python/hands-on/3.1/handsonHtml/whilestatements.html#while-statements
If you're talking about an infinite loop (i.e it has to go on and on without stopping) then simply use
white True:
<Your code here>
If it's not an infinite loop and only till a certain value comes true then you can do something like:
counter = 0
while counter <= 10:
print "This will continue till counter = 10"
counter += 1
You should make a function of the program, this function you can put in a loop. For further help, please post your code!

How to print variable on multiple lines and call on a single piece of code many times in Python?

1.I'm using break to break out of a loop, but I don't know how to make the program keep going no matter what unless this happens. Just typing in while: is invalid (or so the progam tells me) and I want the game to keep going even if the user types in an emptry string.
2.Is there a way to not have to re-type a bit of code every time I need it? I have a bunch of responses for the program to spit out that I'll have to use many times:
if action[0]=='go':
print("You're supposed to go to David!")
elif action[0]=='look':
print("You can't see that")
elif action[0]=='take':
print("You don't see the point in taking that.")
else:
print("I don't recognise that command")
Where action is a list from the player's input. Or do I just have to type it out again each time?
I don't know how to define a function that does the above, and I'm not even sure that's what I'm supposed to do.
3.Some story descriptions I'm using are a very long stings and I don’t want players to have to scroll sideways too much. But I want to just define them as variables to save myself some typing. Is there a way around this. Or do I just have to type it out every time with
print(“““a string here”””)
4.If the string starts with 'look' and has 'floor' or 'mess' or 'rubbish' in it, I want it to print a certain output. This is what I currently have:
if action[0]=='look':
if 'floor' in action or 'rubbish' in action or 'trash' or 'mess' in action:
print('onec')
elif 'screen' in action or 'computer' in action or 'monitor' in action:
print('oned')
elif 'around' in action or 'room' in action or 'apartment' in action:
print('onee')
elif 'david' in action or 'tyler' in action or 'boy' in action or 'brat' in action or 'youth' in action:
print('onef')
break
else:
print("You can't see that")
It prints 'onec' for any input beginning with 'look'.
The while statement requires a condition.
You can call the same instructions over and over using a function.
"String literals can span multiple lines in several ways"
Use strategically-placed print statements to show the value of action, e.g. after if action[0]=='look'
Lastly, please don't add any more items to this question. Rather ask a new question. This site has somewhat specific rules on that sort of thing.
To make an infinite While loop, use while True:.
You could use a dict to store common action strings and their responses.
Just register the string first, then when the input come, change it:
command = "nothing"
command = input("Enter command: ")
while command:
Or just simply:
while True:
Yes, think about it by yourself.. Okay, why not put it in list responses?
If it is really long, put it in a file. Read it when you need it using open(). More on File Processing
This will help you shorten your code, making it easier to read, and makes it more efficient.
while requires a condition that it has to evaluate. If you want it to loop forever, just give it a condition that always evaluates to True, such as 4>3. It would be best for everyone if you just used while True:, which is the clearest option.
For this specific case, I would recommend using a dict() and its .get() method. Something like this:
action_dict = {'go':"You're supposed to go to David!",
'look':"You can't see that",
'take':"You don't see the point in taking that."
}
print(action_dict.get(action[0], "I don't recognise that command")
would replicate what you have going on right now.
See the link provided by cjrh here: http://docs.python.org/3.3/tutorial/introduction.html#strings
Our mind-reading powers are a bit off in October, we'll need some more information other than "it does not work" to help you with that.

Can't kill my python code. What's wrong?

Okay, so I'm writing a very simplistic password cracker in python that brute forces a password with alphanumeric characters. Currently this code only supports 1 character passwords and a password file with a md5 hashed password inside. It will eventually include the option to specify your own character limits (how many characters the cracker tries until it fails). Right now I cannot kill this code when I want it to die. I have included a try and except snippit, however it's not working. What did I do wrong?
Code: http://pastebin.com/MkJGmmDU
import linecache, hashlib
alphaNumeric = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",1,2,3,4,5,6,7,8,9,0]
class main:
def checker():
try:
while 1:
if hashlib.md5(alphaNumeric[num1]) == passwordHash:
print "Success! Your password is: " + str(alphaNumeric[num1])
break
except KeyboardInterrupt:
print "Keyboard Interrupt."
global num1, passwordHash, fileToCrack, numOfChars
print "What file do you want to crack?"
fileToCrack = raw_input("> ")
print "How many characters do you want to try?"
numOfChars = raw_input("> ")
print "Scanning file..."
passwordHash = linecache.getline(fileToCrack, 1)[0:32]
num1 = 0
checker()
main
The way to allow a KeyboardInterrupt to end your program is to do nothing. They work by depending on nothing catching them in an except block; when an exception bubbles all the way out of a program (or thread), it terminates.
What you have done is to trap the KeyboardInterrupts and handle them by printing a message and then continuing.
As for why the program gets stuck, there is nothing that ever causes num1 to change, so the md5 calculation is the same calculation every time. If you wanted to iterate over the symbols in alphaNumeric, then do that: for symbol in alphaNumeric: # do something with 'symbol'.
Of course, that will still only consider every possible one-character password. You're going to have to try harder than that... :)
I think you're also confused about the use of classes. Python does not require you to wrap everything inside a class. The main at the end of your program does nothing useful; your code runs because it is evaluated when the compiler tries to figure out what a main class is. This is an abuse of syntax. What you want to do is put this code in a main function, and call the function (the same way you call checker currently).
Besides printing, you need to actually exit your program when capturin KeyboardInterrupt, you're only printing a message.
This is what worked for me...
import sys
try:
....code that hangs....
except KeyboardInterrupt:
print "interupt"
sys.exit()
Well, when you use that try and except block, the error is raised when that error occurs. In your case, KeyboardInterrupt is your error here. But when KeyboardInterrupt is activated, nothing happens. This due to having nothing in the except part. You could do this after importing sys:
try:
#Your code#
except KeyboardInterrupt:
print 'Put Text Here'
sys.exit()
sys.exit() is an easy way to safely exit the program. This can be used for making programs with passwords to end the program if the password is wrong or something like that. That should fix the except part. Now to the try part:
If you have break as the end of the try part, nothing is going to happen. Why? Because break only works on loops, most people tend to do it for while loops. Let's make some examples. Here's one:
while 1:
print 'djfgerj'
break
The break statement will stop and end the loop immediately unlike its brother continue, which continues the loop. That's just extra information. Now if you have break in a something like this:
if liners == 0:
break
That's going to depend where that if statement is. If it is in a loop, it is going to stop the loop. If not, nothing is going to happen. I am assuming you made an attempt to exit the function which didn't work. It looks like the program should end, so use sys.exit() like I showed you above. Also, you should group that last piece of code (in the class) into a seperate function. I hope this helps you!

Categories

Resources