Submit command line // submit unfilled raw_input - python

I'm looking to write a program that asks for user_input on a cyclical basis, but does not halt further procedures while waiting for the user to give input.
Is there a command that acts as a press of the RETURN key? Does this have to do with writing to stdin? An alternative might be to see if there is no user_input that currently exists.
Imagine operating the code below, where the program is constantly running, even if the user provides no input,
import os
import time
import termios
import sys
x = 0
while x < 60:
time.sleep(0.5)
x += 1
print x
user_input = raw_input(" ")
if user_input == "exit":
os._exit(1)

Related

python not taking input after subprocess is called with subprocess.popen

Hello everyone im fairly new to python and this is my first language im learning so far. Im making a menu using a while true loop that takes input to select whichever flashing method a person needs to use and after calling whatever file using subprocess.popen or subprocess.call and it finishes it goes back into the menu loop but does not respond to any input at all.
import sys
import time
import subprocess
#!/bin/bash
sys.path.append
menu = True
def mainMenu():
while menu:
print("""
##################
# Utilities Menu #
##################
1. Tray Flasher
2. ESP Burner
3. Quit
""")
choice = (input('Select a utility: '))
if choice == '1':
trayFlasher()
elif choice == '2':
espBurner()
elif choice == '3':
print('Goodbye!')
def trayFlasher():
print('Have Fun!')
time.sleep(1)
subprocess.call(["<path to file>"])
def espBurner():
print('Burn Baby Burn...')
time.sleep(1)
subprocess.Popen(['<path to file>'])
sorry if my code is not so good or efficient, currently still learning. TIA!

none stop while loop responsive to user key press

I have a while that do something in an infinite, nonstop loop.
It should not be stopped or wait for user input.
But I need user can stop while with specific key press.
For example if user press f do someting new or p something else.
How should I get user key press in a nonstop while?
n = 1
while True:
# do somthing
n += 1
if <press p >
# do task 1
if <press f >
# exit while
## do somthing else
I can't use keyboard library because need sudo privilege on Linux
As stated on "How about nope"'s answer, that is not straightforward.
One can either go into the low level of the input system and change some settings to allow for non-blocking keyboard reading, or makeuse of a thirdy party library that will do that and provide some friendly interface.
terminedia is one such 3rdy party project - among other niceties, it implements the inkey() call which is similar to old-time BASIC function with the same name: it returns the key currently pressed, if there is one, or an empty string.
You just have to call it inside a context block using the terminedia keyboard: with terminedia.keyboard:
So, you have to first install terminedia in your Python environment with pip install terminedia. Then your code could be like this:
import terminedia as TM
n = 1
with TM.keyboard:
while True:
# do something
n += 1
if (pressed:=TM.inkey()) == "p":
# do task 1
if pressed == "f":
# exit while
break
Another advantage over writing the code to set stdin settings is that
terminedia keyboard input is multiplatform and will work in windows (though much of the other functionalities in the lib will be Unix only)
(disclaimer: I am the project author)
As #Kris said in comment, threading + queue can do a trick. Here is just an example, it needs a few fixes (messes up terminal look) but should be a great start for you (this won't work on windows in this form, but just to give you example how to use it). Also, before using threading please read docs of threading, especially parts about global interpreter lock
import sys
import tty
import threading
import queue
import termios
def watcher(q: queue.Queue):
# To bring back terminal look. More info here https://docs.python.org/3/library/termios.html
fd = sys.stdin.fileno()
old_Settings = termios.tcgetattr(fd)
while True:
# Reads 1 char form sdin without need of newline
tty.setraw(sys.stdin.fileno())
i = sys.stdin.read(1)
if i == "p":
q.put_nowait("p")
termios.tcsetattr(fd,termios.TCSADRAIN,old_Settings)
elif i == "f":
q.put_nowait("f")
termios.tcsetattr(fd,termios.TCSADRAIN,old_Settings)
break
def runner(q: queue.Queue):
n = 1
while True:
n += 1
# You need to check if q is empty, or It will throw an empty err
if not q.empty():
key = q.get_nowait()
if key == "f":
print("Got exit event after {} loops".format(n))
break
if key == "p":
print("Got p after {} loops".format(n))
if __name__ == "__main__":
# Queue setup and 2 threads.
q = queue.Queue()
x = threading.Thread(target=watcher, args=(q,))
x.start()
y = threading.Thread(target=runner, args=(q,))
y.start()
Output afrer running:
python3 ../../test.py
Got p after 1055953 loops
Got exit event after 4369605 loops

How can I take input from the user above a printed line?

How can I print directly after my input without waiting until the user answered the input statement?
def InputSaveName():
try:
import os, sys, time, pickle, colorama
except Exception as e:
print("Some modules are mssing! Install them and try again! {}".format(e))
colorama.init()
print("+----------------------+")
print("What is your name adventurer?")
name = input("> ")
print("+----------------------+")
I want the bottom line to print without waiting for the user to put something in the input statement. In short: I want the code to run simultaneously.
This seems to be an XY problem. You do not really want to use threading to run multiple lines of code at once. To build a complex full-screen terminal application, you should have a look at curses:
import curses
def getname(stdscr):
stdscr.clear()
stdscr.addstr(0, 0, "+---------------------------+")
stdscr.addstr(1, 0, "What is your name adventurer?")
stdscr.addstr(2, 0, "> ")
stdscr.addstr(3, 0, "+---------------------------+")
curses.echo()
return stdscr.getstr(2, 3, 20)
s = curses.wrapper(getname)
print("Name is", s)
This only asks for the name and then returns, but you can also add lines, or replace existing lines on the existing screen and refresh the screen.
Without being 100% sure if it works in the specific examples you have typed in your question because of access to the standard output.
If you want to run things in parallel you can read about threads / subprocess https://docs.python.org/3/library/subprocess.html
or fork / multiprocessing
https://docs.python.org/3/library/multiprocessing.html
EDIT after op's EDIT ;-)
What you want to do seems very similar to what's described in this question Python nonblocking console input
This might be what you are looking for.
There is a "background process" running while waiting for your input using two separate threads.
import time
import threading
def myInput():
print("Type your name when ready!")
name = input()
print("Your name is: ", name)
def backgroundProcess():
while (True):
print("Some code is running...")
time.sleep(1)
inputThread = threading.Thread(target=myInput)
processThread = threading.Thread(target=backgroundProcess)
inputThread.start()
processThread.start()
You can use threading or multiprocessing modules:
import threading
def makeAsomethingOne():
print('I am One!')
def makeAsomethingTwo(printedData=None):
print('I am Two!',printedData)
name = input("> ")
firstThread = threading.Thread(target=makeAsomethingOne)
twiceThread = threading.Thread(target=makeAsomethingTwo,args=[name])
firstThread.start()
twiceThread.start()
This code runs almost simultaneously.

Python | IF statment stop script after user input has been made

I am currently working on a automated troubleshooter using Python. Below is a piece of my script which I need help with.
s1 = input("Is your phone freezing/stuttering? ")
if s1 == "Yes" or s1 == "yes":
print("Try deleting some apps and this might help with your problem.")
if s1 == "No" or s1 == "no":
def foo():
while True:
return False
So what I want to happen is my script to stop when the user types in YES and when the solution to the fix comes up. Is there a possible loop for that or something similar? Also if the user types in NO then I want the script to continue to the next question.
So one thing that you can do is utilize the sys.
So you can modify your program to look like the following:
import sys
s1 = input("Is your phone freezing or stuttering (yes/no)? ")
if s1.lower() == "yes":
print("Deleting some apps and this might help!")
elif s1.lower() == "no":
print("Your phone is working fine! Program is terminating.")
sys.exit(0) # this exits your program with exit code 0
The sys package is great for program control and also interacting with the interpreter. Please read more about it here.
If you don't want your program to exit and you just want to check that the user entered no, you could do something like:
import sys
s1 = input("Is your phone freezing or stuttering (yes/no)? ")
if s1.lower() == "yes":
print("Deleting some apps and this might help!")
elif s1.lower() == "no":
pass
else:
# if the user printed anything else besides yes or no
print("Your phone is working fine! Program is terminating.")
sys.exit(0) # this exits your program with exit code 0
Let me know if I can help in any other way!
EDIT
A comment by crickt_007 suggested that it might be helpful to repeat the input and continually query the user. You could wrap this whole function in a while loop then.
import sys
while True:
s1 = input("Is your phone freezing or stuttering (yes/no)? ")
if s1.lower() == "yes":
print("Deleting some apps and this might help!")
# solve their issue
elif s1.lower() == "no":
# supposedly move on to the rest of the problem
pass
else:
# if the user printed anything else besides yes or no
# maybe we want to just boot out of the program
print("An answer that is not yes or no has been specified. Program is terminating.")
sys.exit(0) # this exits your program with exit code 0
A while loop sounds like what you are looking for?
import sys
s1 = "no"
while s1.lower() != 'yes':
input("Is your phone freezing/stuttering? ")
if s1.lower() == 'yes':
print("Try deleting some apps and this might help with your problem.")
sys.exit(0)
elif s1.lower() == 'no':
print("something")
else:
print("invalid input")

Python - Infinite while loop, break on user input

I have an infinite while loop that I want to break out of when the user presses a key. Usually I use raw_input to get the user's response; however, I need raw_input to not wait for the response. I want something like this:
print 'Press enter to continue.'
while True:
# Do stuff
#
# User pressed enter, break out of loop
This should be a simple, but I can't seem to figure it out. I'm leaning towards a solution using threading, but I would rather not have to do that. How can I accomplish this?
You can use non-blocking read from stdin:
import sys
import os
import fcntl
import time
fl = fcntl.fcntl(sys.stdin.fileno(), fcntl.F_GETFL)
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, fl | os.O_NONBLOCK)
while True:
print("Waiting for user input")
try:
stdin = sys.stdin.read()
if "\n" in stdin or "\r" in stdin:
break
except IOError:
pass
time.sleep(1)
I think you can do better with msvcrt:
import msvcrt, time
i = 0
while True:
i = i + 1
if msvcrt.kbhit():
if msvcrt.getwche() == '\r':
break
time.sleep(0.1)
print(i)
Sadly, still windows-specific.
On python 3.5 you can use the following code. It can be adjusted for a specific keystroke. The while loop will keep running until the user presses a key.
import time
import threading
# set global variable flag
flag = 1
def normal():
global flag
while flag==1:
print('normal stuff')
time.sleep(2)
if flag==False:
print('The while loop is now closing')
def get_input():
global flag
keystrk=input('Press a key \n')
# thread doesn't continue until key is pressed
print('You pressed: ', keystrk)
flag=False
print('flag is now:', flag)
n=threading.Thread(target=normal)
i=threading.Thread(target=get_input)
n.start()
i.start()
I could not get some of the popular answers working. So I came up with another approach using the CTRL + C to plug in user input and imbibe a keyboard interrupt. A simple solution can be using a try-catch block,
i = 0
try:
while True:
i+=1
print(i)
sleep(1)
except:
pass
# do what you want to do after it...
I got this idea from running a number of servers like flask and django. This might be slightly different from what the OP asked, but it might help someone else who wanted a similar thing.
Using the msvcrt module as thebjorn recommended I was able to come up with something that works. The following is a basic example that will exit the loop if any key is pressed, not just enter.
import msvcrt, time
i = 0
while True:
i = i + 1
if msvcrt.kbhit():
break
time.sleep(0.1)
print i
What you need is a non-blocking raw input, if you don't want to use threads there is a simple solution like this one below where he is doing a timeout of 20 ms and then raise and exception if the user doesn't press a key, if he does then the class returns the key pressed.
import signal
class AlarmException(Exception):
pass
def alarmHandler(signum, frame):
raise AlarmException
def nonBlockingRawInput(prompt='', timeout=20):
signal.signal(signal.SIGALRM, alarmHandler)
signal.alarm(timeout)
try:
text = raw_input(prompt)
signal.alarm(0)
return text
except AlarmException:
print '\nPrompt timeout. Continuing...'
signal.signal(signal.SIGALRM, signal.SIG_IGN)
return ''
Source code
I have defined the function which ask number input from the user and returns the factorial of that number. If user wants to stop they have to press 0 and then it will exit from the loop. We can specify any specific key to input 'n' to exit from the loop.
import math
def factorial_func(n):
return math.factorial(n)
while True:
n = int(input("Please enter the number to find factorial: "))
print(factorial_func(n))
if n == 0:
exit()

Categories

Resources