raw_input prints prompt after asking for input - python

When I use raw_input, the prompt only shows after the user gives input. Like this:
number = raw_input("Enter a number:")
but when I run this, nothing happens, the I type a number, the it shows the prompt:
123
Enter a number:
(123 used to be blank until I typed a number and hit enter)
I just want the prompt to display before the user input. If anybody knows how to fix this please help.
Thanks.

You might be in an environment where your standard output is buffered and won't flush until there is a newline character.
You can take advantage of the fact the standard error is unbuffered and redirect standard output to standard error instead:
import sys
sys.stdout = sys.stderr

Thanks for you suggestion, and I did try that, but unfortunately it didn't work, but I did find the solution:
I had to add
sys.stdout.flush()
before each time I had a
variable = raw_input("A prompt")
to flush the buffer.
Although for the first
raw_input("A prompt")
it will not work work unless you already printed something, for example
variable = raw_input("A prompt")
sys.stdout.flush()
would still have the same issue, whereas
print"Welcome,"
variable = raw_input("A prompt")
sys.stdout.flush()
would work.

Related

Get user console input before user hitting enter

I have a quite simple problem.
I want to get some console input from a user (without an enter press at the end) and do something with it right away.
I quickly saw that the input() function from python would not work. I thought maybe you could write something like this:
sys.stdout.write("Input: ")
while True:
line = sys.stout.readline()
// Do something with the lines
But unfortunately it does not work because stdout is not readable. With stdin it does not work either because it waits for a enter press of the user.
Is it somehow possible to get lines without the user submit it?
You can get input from console interactively in byte format instead of getting a string with input command.
import sys
while True:
c = sys.stdin.read(1) # Read one byte
Here is what you might be looking for.
To get this working you will need to use pip install keyboard in the command line first.
import keyboard
while True:
key_pressed = keyboard.read_key()
print(f'You pressed {key_pressed}.')

Why does my standalone program exits without giving me a chance to read the results (python)?

I am a complete beginner in python as well as this website.
Background:
I have tried to program a random password generator that allows the user to input the length of the password and how many passwords the user wants.
Everything works perfectly fine when I run the program in pharm. So I converted the script into .exe file. It does not crash instantly, it stills allow the user to input values but once the user entered the values in, it crashes.
I tried using pyinstaller from youtube tutorials to "properly" convert the script into .exe, but the same result still occurs. (Previously, I simply copy and paste my script into notepad and name that notepad in terms of .py and run it.)
Here are my codes:
import random
import sys
chars = "abcdefghijklnmopqrstuvwxyzABCDEFGHIJKLNMOPQRSTUVWXYZ0123456789!##$%^&*+="
try:
length_password = int(input("Enter the length of your password: "))
how_many = int(input("Enter how many passwords you want: "))
except:
print("Invalid input (numbers only!)")
sys.exit()
def length_function(length):
password = ""
for number_times in range(0, length_password):
password = password + random.choice(chars)
return password
print("Here are your passwords: ")
number_times1 = 1
while number_times1 <= how_many:
print(length_function(length_password))
number_times1 = number_times1 + 1
Like I mentioned before, it runs well in pycharm but not in a .exe file.
I've seen your other question and try to explain more on the solution for this problem:
When running a code, program, or whatever, that code might end somewhere, where nothing has to be done anymore.
That's the point where your operating system (Windows, Linux etc) just exits the program. What you might expect is that the console stays open so you can read the ouput, right?
So why does this often work but often doesn't?
When calling your code from an already existing command window (for e.g. cmd.exe), the console (which is a program itself) is not finished and won't close after runnning your program. That's the point where you can read the printed output from you own program.
When you call your program from somewhere else, it is opening a console just for that purpose and it's configured in that way, that it doesn't stay open after executing your program. So when your code is executed, it prints something on the console; but immediately after its done and the console closes, too.
That is where the solution input("Press Enter to exit") comes into play. input() is a function which waits for user input; so it's waiting infinitely for you to hit enter. That means, your program is not finished. That gives you the time you read the output you want to read.

When using sys.stdin.read(), why I am not able to input from keyboard?

My code is as follows:
def function(a, b):
while a != 0 and b != 0:
...
return x
if __name__ == "__main__":
input = sys.stdin.read()
a, b = map(int, input.split())
print(function(a, b))
When I try to run it, the program doesn't give me a chance to input.
I get the following traceback message:
ValueError: not enough values to unpack (expected 2, got 0)
Can someone tell me the reason and how I can make input to test my program.
Thanks a lot.
sys.stdin.read() will read stdin until it hits EOF. Normally, this happens when that stream is closed by the other end (i.e. by whatever provides input).
This works if you run your program like cat inputfile.txt | your_program. But it will just keep reading endlessly in interactive mode when stdin is connected to your terminal, so the only way to close it from the other end is to close the terminal.
Strictly speaking, you can make read() stop by inputting a EOF character on a line by itself which is Ctrl-D in Unix and Ctrl-Z in Windows -- and this works in a regular Python console. But in IPython, this technique doesn't work: here in Windows, I see Ctrl-D as \x04 and Ctrl-Z as a blank line and neither stops the read (whether this is a bug or by design is another question).
So,
Use input() instead to input a single line, or
if you require multiple lines of input, use something that puts a limit on how much is read from stdin:
ll=[]
while True:
l = input() # or sys.stdin.readline().rstrip()
if not l: break
ll.append(l)
This way, you're able to stop the program from asking for more input by entering a blank line.
finally, there's sys.stdin.isatty() which allows you do invoke different code depending on whether the input is interactive (but for your task, this is probably an overkill).

Killing stdout in python breaks get_line_buffer()

So I'm using some libraries that (unfortunately and much to my chagrin) print to stdout for certain debug info. Okay, no problem, I just disabled it with:
import sys,os
sys.stdout = open(os.devnull,'wb')
I've recently added code for getting user input and printing output in the terminal, which of course needs stdout. But again, no problem, instead of print I can just do:
sys.__stdout__.write('text\n')
Finally, since I'm doing raw_input in a separate thread and the program's output can interrupt the user typing, I wanted to re-echo the test as described in the first part of this answer to make it more or less seamless using readline.get_line_buffer(). For example, if the user entered foobar:
> foobar
And then another thread says Interrupting text! it should look like:
Interrupting text!
> foobar
But instead I observe:
Interrupting text!
>
It turns out that readline.get_line_buffer() is always blank, and the code fails to re-echo what the user had typed. If I remove the sys.stdout override, everything works as expected (except now the debug output from libraries isn't blocked).
I'm using Python 2.7 on Linux if that matters. Perhaps what I want to do is impossible, but I'd really like to know why this is happening. In my mind, doing things with stdout shouldn't affect the stdin line buffer, but I'm admittedly not familiar with the underlying libraries or implementation.
A minimum working example is below. Just type something and wait for the interrupting text. The prompt "> " will be re-echoed, but the text you entered won't be. Simply comment out the second line to see it work correctly. When the thread prints, it logs the line buffer to stdin.log.
import time,readline,thread,sys,os
sys.stdout = open(os.devnull,'wb') # comment this line!
def noisy_thread():
while True:
time.sleep(5)
line = readline.get_line_buffer()
with open('stdin.log','a') as f:
f.write(time.asctime()+' | "'+line+'"\n')
sys.__stdout__.write('\r'+' '*(len(line)+2)+'\r')
sys.__stdout__.write('Interrupting text!\n')
sys.__stdout__.write('> ' + line)
sys.__stdout__.flush()
thread.start_new_thread(noisy_thread, ())
while True:
sys.__stdout__.write('> ')
s = raw_input()
I've also tried sys.stdout = sys.__stdout__ right before the get_line_buffer() call, but that doesn't work either. Any help or explanation is greatly appreciated.
Its the raw_input() that stops working when you redirect the stdout.
If you try sys.stdout = sys.__stdout__ just before the raw_input() it works again.
Both stdin and stdout need to be connected to the terminal in order for raw_input to work.

Save a Python script's output with > in bash while using raw_input()

This is a weird one that's so general I can't to properly narrow the search terms to find an answer.
My python script has a raw_input to prompt the user for values. But, when I try to run the script and funnel it into a file, it crashes.
Something like "script.py > save.txt"
wont work. It doesn't even properly prompt me at the command line for my input. There doesn't seem to be anything indicating why this doesn't work as intuitively as it should.
raw_output prints its prompt to stdout, which you are redirecting to a file. So your prompt will end up in the file and the program does not appear to show a prompt. One solution is to output your prompt to stderr.
import sys
sys.stderr.write('prompt> ')
value = raw_input()
print('value was: ', value)
You could also avoid using both pipes and interactive input with the same script. Either take input from command line flags using argparse and use pipes, or create an interactive program that saves output to a file itself.
Depending on your program's logic, you can also check whether stdout is connected to a live console or not:
is_tty = os.isatty(sys.stdout.fileno())
Dolda2000 also has a good point about writing to /dev/tty, which will write to the controlling terminal of the script being run even if both stdin and stderr are redirected. The deal there, though, is that you can't use it if you're not running in a terminal.
import errno
try:
with open('/dev/tty', 'w') as tty:
tty.write('prompt> ')
except IOError as exc:
if exc.errno == errno.ENXIO:
pass # no /dev/tty available
else:
pass # something else went wrong

Categories