I do not know how to ask a user for input giving him a hint at the same time.
When I use raw_input("some description") a small window pops up and the user must enter something, as the input is completely empty. How to achieve the same, but with something already written to the input box (a hint for the user, which he/she could accept or simply change it)?
This has been answered before:
https://stackoverflow.com/a/2533142/1217949
The standard library functions input() and raw_input() don't have this functionality. If you're using Linux you can use the readline module to define an input function that uses a prefill value and advanced line editing:
def rlinput(prompt, prefill=''):
readline.set_startup_hook(lambda: readline.insert_text(prefill))
try:
return raw_input(prompt)
finally:
readline.set_startup_hook()
Related
I have a project that involves asking for (for now, command-line) feedback from the user every so often while its main method runs.
So far I have been using input('{my_prompt}') to obtain this input from my user, but I have to quite annoyingly handle user input every time I invoke input(). This makes my code balloon to > 5 lines of code per user input line, which feels quite excessive. Some of my user input handling includes the below.
if input.lower() not in ['y', 'n']:
raise ValueError('Not valid input! Please enter either "y" or "n"')
if input.lower() == 'y':
input = True
else:
input = False
The above could be handled in 1 line of code if the user were passing command line arguments in and I could use argparse, but unfortunately the sheer volume of prompts prevents command line arguments from being a viable option.
I am familiar with the libraries cmd and click, but as far as I can tell, they both lack the functionality that I would like from argparse, which is namely to validate the user input.
In summary, I'm looking for a user input library that validates input and can return bool values without me having to implement the conversion every time.
If all you need is to check "yes/no" prompts, click supports it natively with click.confirm:
if click.confirm("Do you want to do this thing?"):
# ... do something here ....
There are a variety of other input-handling functions part of click, which are documented in the User Input Prompts section of the documentation.
I have a python script that runs and accepts user input to make decisions. Based on the input I would like to give the user control of the python repl. Here is an example:
def func():
# hand over control to the user
breakpoint()
while True:
print('What would you like to do?\nq: quit\ni: interact')
i = input()
if i=='q':
break
elif i=='i':
func()
else:
print(f'invalid command: {i}')
Calling this code snippet with for example ipython3, the user is prompted for input. When the user presses i, func() is called, at which point I would like the user to be able to type python commands such as print(i).
My current best solution is to then set a breakpoint, the user may then need to type r to get to the right frame and then must then type interact. This is nearly acceptable, but I would like my user to not need to know that I'm using a debugger to give them interactive control, rather I would like them to be given an ipython prompt directly.
I looked at this post from 10 years ago: Jump into a Python Interactive Session mid-program? rz.'s comment looks interesting, but it looks like too much has changed for me to use his answer as is, plus there may be newer ways of doing things.
Python3: I'm trying to allow a user a given amount of time to enter a response into an input, but after a given amount of time if they haven't entered anything, I want to abort the input and assign a default value to the variable that is storing the input, or otherwise feed default values into the input statement after the given time period.
I've tried this:
from threading import Timer
timeout = 2
t = Timer(timeout, print, ["\nSorry, time is up"])
t.start()
answer = input("You have 2 seconds to answer:")
t.cancel()
print(answer)
from a different stack overflow post, but the problem is that the interpreter still prompts the user for input even after the final line is executed and answer is printed, and this won't work for what I'm trying to do (essentially, a command line game that needs to keep going when the player isn't giving it input but update when it does receive input).
What is the best way to do this? I know python doesn't really have a timeout function or something like that, but is there any way to achieve this via system commands or a module?
There are several plausible approaches (some of which are probably Unix-specific):
Read the input in a subprocess that can be killed after the timeout. (Many functions, including subprocess.run, accept a timeout parameter to automate this.)
Use alarm or similar to send your own process a signal (and install a signal handler that throws an exception).
Have another thread close the descriptor being read after the timeout; this sounds drastic but is generally said to work, so long as you don’t accidentally open a file on the closed descriptor before restoring it with dup2.
Read the input with lower-level facilities like non-blocking read and select—which will unfortunately disable nice things like readline.
In any case, you have to decide what to do with incomplete but non-empty input entered before the timeout. The terminal driver will likely transfer it invisibly to the next input prompt by default.
Using a select call may be a easier way.
import sys, select
print "You have ten seconds to answer!"
i, o, e = select.select( [sys.stdin], [], [], 10 )
if (i):
print "You said", sys.stdin.readline().strip()
else:
print "You said nothing!"
Refer to Keyboard input with timeout?
I'm writing a script that needs some very simple input from the user, and upon doing my research on this I am in a dilemma trying to work out the safest way to do it.
I only want an integer and stumbled across (what I thought was) a nice piece of code similar to (doing this from memory):
def getNumeric(prompt):
while True:
response = input(prompt)
try:
return int(response)
except ValueError:
print "please enter a number:",
This mostly worked, but if the user just pressed [enter] then it crashed. Turns out, I'm using python < 3, and the author wrote this for 3+. So now I have to rewrite for 2.7 to suit my needs. But how do I write it to cater for EITHER platform <3 and 3+?
I am writing something that could be used by others and want to make it the most portable I can. Should I bother?
As an aside, I am doing this for the Raspberry Pi, should I upgrade my python to 3, or leave it where it is (2.7.3)?
My suggestion is to upgrade the Pi to Python 3. There's no point developing Python code for two separate versions (unless it's a library, which you'd use much more precautions than just sharing functions). You can do:
# Python 3.x
def getNumeric(prompt):
while True:
try:
res = int(input(prompt))
break
except ValueError:
print("Numbers only please!")
return res
For Python 2.7.x, use raw_input() instead of input(). input() in Python 2 is not considered save since it evaluates the string given (and can be malicious).
Try:
def getNumeric(prompt):
while True:
response = input(prompt)
try:
if isinstance(response, int):
return int(response)
else:
print "please enter a number:"
except ValueError:
print "please enter a number:"
I am trying to make a program which has a raw_input in a loop, if anyone presses a key while the long loop is running the next raw_input takes that as input, how do I avoid that?
I don't know what else to add to this simple question. Do let me know if more is required.
EDIT
Some code
for i in range(1000):
var = raw_input("Enter the number")
#.... do some long magic and stuff here which takes afew seconds
print 'Output is'+str(output)
So if someone presses something inside the magic phase, that is take as the input for the next loop. That is where the problem begins. (And yes the loop has to run for 1000 times).
This works for me with Windows 7 64bit, python 2.7.
import msvcrt
def flush_input():
while msvcrt.kbhit():
msvcrt.getch()
I put the OS in the title, window 7 64 bit to be specific. I saw the
answers there. They do apply but by god they are so big. Aren't there
other n00b friendly and safer ways to take inputs?
Let me try to explain why you need to do such an elaborate process. When you press a key it is stored in a section of computer memory called keyboard buffer (not to be confused with stdin buffer). This buffer stores the key's pressed until it is processed by your program. Python doesn't provide any platform independent wrapper to do this task. You have to rely on OS specific system calls to access this buffer, and flush it, read it or query it. msvcrt is a MS VC++ Runtime Library and python msvcrt provides a wrapper over it. Unless you wan't a platform independent solution, it is quite straight forward.
Use msvcrt getch to read a character from console. msvcrt.kbhit() to test if a key press is present in the keyboard buffer and so on. So as MattH has shown, it just a couple of lines code. And if you think you are a noob take this opportunity to learn something new.
Just collect your input outside of the loop (before you enter the loop). Do you really want the user to enter 1000 numbers? well maybe you do. but just include a loop at the top and collect the 1000 numbers at the start, and store them in an array.
then on the bottom half change your loop so it just does all the work. then if someone enters something no the keyboard, it doesn't really matter anymore.
something like this:
def getvars(top=1000):
vars = []
for i in range(0,top):
anum = int(raw_input('%d) Please enter another number: ' % i))
vars.append(anum)
return vars
def doMagic(numbers):
top = len(numbers)
for number in numbers:
# do magic number stuff
print 'this was my raw number %s' % number
if __name__ == "__main__":
numbers = getvars(top=10)
doMagic(numbers)
presented in a different sort of way and less os dependent
There is another way to do it that should work. I don't have a windows box handy to test it out on but its a trick i used to use and its rather undocumented. Perhaps I'm giving away secrets... but its basically like this: trick the os into thinking your app is a screensaver by calling the api that turns on the screensaver function at the start of your magic calculations. at the end of your magic calculations or when you are ready to accept input again, call the api again and turn off the screensaver functionality.
That would work.
There is another way to do it as well. Since you are in windows this will work too. but its a fair amount of work but not really too much. In windows, the window that is foreground (at the top of the Z order) that window gets the 'raw input thread'. The raw input thread receives the mouse and keyboard input. So to capture all input all you need to do is create a function that stands up a transparent or (non transparent) window that sits at the top of the Z order setWindowPos would do the trick , have it cover the entire screen and perhaps display a message such as Even Geduld or Please wait
when you are ready to prompt the user for more input, you use showwindow() to hide the window, show the previous results, get the input and then reshow the window and capture the keys/mouse all over again.
Of course all these solutions tie you to a particular OS unless you implement some sort of try/except handling and/or wrapping of the low level windows SDK calls.