I made a small program in Python (.py) and converted it into a Windows executable file (.exe) using Py2exe. It asks for a string and then outputs a string -- very simple! -- and works flawlessly in Python.
However, when the exe file finishes execution in the command window, the command window closes automatically before I can get a glimpse of its output (I assume it does print the output because, like I said, it works flawlessly in Python).
How can I prevent this from happening? I assume I need to change my code, but what exactly do I need to add to it?
Here is my code, in case it helps you to see it (it's a word-wrapper):
import string
def insertNewlines(text, lineLength):
if text == '':
return ''
elif len(text) <= lineLength:
return text
elif text[lineLength] == ' ':
return text[:lineLength] + '\n' + insertNewlines(text[lineLength+1:], lineLength)
elif text[lineLength-1] == ' ':
return text[:lineLength] + '\n' + insertNewlines(text[lineLength:], lineLength)
else:
if string.find(text, ' ', lineLength) == -1:
return text
else:
return text[:string.find(text,' ',lineLength)+1] + '\n' + insertNewlines(text[string.find(text,' ',lineLength)+1:], lineLength)
print
if __name__ == '__main__':
text = str(raw_input("Enter text to word-wrap: "))
lineLength = int(raw_input("Enter number of characters per line: "))
print
print insertNewlines(text, lineLength)
Thank you.
The simplest way is probably to use raw_input() just before your program finishes. It will wait until you hit enter before closing.
if __name__ == '__main__':
text = str(raw_input("Enter text to word-wrap: "))
lineLength = int(raw_input("Enter number of characters per line: "))
print
print insertNewlines(text, lineLength)
raw_input()
Just put this at the end of your code:
junk = raw_input ("Hit ENTER to exit: ")
In other words, your main segment should be:
if __name__ == '__main__':
text = str(raw_input("Enter text to word-wrap: "))
lineLength = int(raw_input("Enter number of characters per line: "))
print
print insertNewlines(text, lineLength)
junk = raw_input ("Press ENTER to continue: ")
This is what I use in my scripts:
#### windows only ####
import msvcrt
def readch(echo=True):
"Get a single character on Windows."
while msvcrt.kbhit():
msvcrt.getch()
ch = msvcrt.getch()
while ch in b'\x00\xe0':
msvcrt.getch()
ch = msvcrt.getch()
if echo:
msvcrt.putch(ch)
return ch.decode()
def pause(prompt='Press any key to continue . . .'):
if prompt:
print prompt,
readch()
######################
Sometimes though, I just use the following to make the window stay open for a short time before closing.
import time
time.sleep(3)
Related
So I made a very simple Auto-typer and want to be able to run it again or quit it.
All works perfectly fine but at the end the "ending = input()" doesnt let me type it just exits out of the programm. Any reason why?
import pyautogui
import time
import os
def clearConsole():
command = 'clear'
if os.name in ('nt', 'dos'): # If Machine is running on Windows, use cls
command = 'cls'
os.system(command)
break_loop = 1
while break_loop <= 1:
secs_inbetween_actions = float(input("""
Seconds between actions(should be float but int is also ok): """))
no_of_lines = int(input("""
How many Lines do you want to write?(Only int): """))
time_between_action = int(input("""
How long should the time between enter and writing be?: """))
lines = ""
print("""
Write your Text under this message (You have """ + str(no_of_lines) + """ line(s) to wite)
""")
for i in range(no_of_lines):
lines += input() + "\n"
print("-------------------------------------")
while time_between_action > 0:
time_between_action = time_between_action - 1
print('Time Left until writing -+==> ' + str(time_between_action))
time.sleep(1)
print("-------------------------------------")
pyautogui.typewrite(lines, interval=secs_inbetween_actions)
ending = input("If you want to use this aplication once again type 'y' + 'enter key' ,if not press the 'enter key': ")
if ending == "y":
break_loop = 1
clearConsole()
else:
break_loop += 1
This is a rather fun little problem. It occurs, as #Barmar notes, because pyautogui.typewrite() is writing to the console for you. I incorrectly thought that it was not happening when there was no delay between actions, which was a far more puzzling little problem.
In this case the solution is easy: add after your typewrite():
if lines:
input()
To absorb what has just been typed for you.
Let's say I want to pipe input to a Python program, and then later get input from the user, on the command line.
echo http://example.com/image.jpg | python solve_captcha.py
and the contents of solve_captcha.py are:
import sys
image_url = sys.stdin.readline()
# Download and open the captcha...
captcha = raw_input("Solve this captcha:")
# do some processing...
The above will trigger a EOFError: EOF when reading a line error.
I also tried adding a sys.stdin.close() line, which prompted a ValueError: I/O operation on closed file.
Can you pipe information to stdin and then later get input from the user?
Note: This is a stripped down, simplified example - please don't respond by saying "why do you want to do that in the first case," it's really frustrating. I just want to know whether you can pipe information to stdin and then later prompt the user for input.
There isn't a general solution to this problem. The best resource seems to be this mailing list thread.
Basically, piping into a program connects the program's stdin to that pipe, rather than to the terminal.
The mailing list thread has a couple of relatively simple solutions for *nix:
Open /dev/tty to replace sys.stdin:
sys.stdin = open('/dev/tty')
a = raw_input('Prompt: ')
Redirect stdin to another file handle when you run your script, and read from that:
sys.stdin = os.fdopen(3)
a = raw_input('Prompt: ')
$ (echo -n test | ./x.py) 3<&0
as well as the suggestion to use curses. Note that the mailing list thread is ancient so you may need to modify the solution you pick.
bash has process substitution, which creates a FIFO, which you can treat like a file, so instead of
echo http://example.com/image.jpg | python solve_captcha.py
you can use
python solve_capcha.py <(echo http://example.com/image.jpg)
You would open first argument to solve_capcha.py as a file, and I think that sys.stdin would still be available to read input from the keyboard.
Edit: if you're not using bash, you can use mkfifo to accomplish the same thing on any POSIX system:
mkfifo my_pipe
echo "http://example.com/image.jpg" > my_pipe
python solve_captcha.py my_pipe
The FIFO will block (wait without closing) for output.
You can close stdin and then reopen it to read user input.
import sys, os
data = sys.stdin.readline()
print 'Input:', data
sys.stdin.close()
sys.stdin = os.fdopen(1)
captcha = raw_input("Solve this captcha:")
print 'Captcha', captcha
Made this up to emulate raw_input(), since I had the same problem as you. The whole stdin and clear ugliness is simply to make it look pretty. So that you can see what you are typing.
def getInputFromKeyPress(promptStr=""):
if(len(promptStr)>0):
print promptStr
"""
Gets input from keypress until enter is pressed
"""
def clear(currStr):
beeString, clr="",""
for i in range(0,len(currStr)):
clr=clr+" "
beeString=beeString+"\b"
stdout.write(beeString)
stdout.write(clr)
stdout.write(beeString)
from msvcrt import kbhit, getch
from sys import stdout
resultString, userInput="", ""
while(userInput!=13):
if (kbhit()):
charG=getch()
userInput= ord(charG)
if(userInput==8):#backspace
resultString=resultString[:-1]
clear(resultString)
elif(userInput!=13):
resultString="".join([resultString,charG])
clear(resultString)
stdout.write(resultString)
if(userInput==13):
clear(resultString)
#print "\nResult:",resultString
return resultString.strip()
I updated #Bob's answer to support delete, ctrl + [left, right, home, end] keypresses and simplified the stdout clearing and rewriting.
def keypress_input(prompt_str=""):
"""
Gets input from keypress using `msvcrt` until enter is pressed.
Tries to emulate raw_input() so that it can be used with piping.
:param prompt_str: optional string to print before getting input
:type prompt_str: str
"""
from re import finditer
from msvcrt import getch
from sys import stdout
# print even if empty to create new line so that previous line won't be overwritten if it exists
print prompt_str
user_input = ""
curr_chars = []
cursor_pos = 0
backspace = 8
enter = 13
escape_code = 224
delete = 83
left = 75
right = 77
home = 71
end = 79
ctrl_left = 115
ctrl_right = 116
ctrl_home = 119
ctrl_end = 117
while user_input != enter:
char_g = getch()
user_input = ord(char_g)
prev_len = len(curr_chars) # track length for clearing stdout since length of curr_chars might change
if user_input == backspace:
if len(curr_chars) > 0 and cursor_pos <= len(curr_chars):
cursor_pos -= 1
curr_chars.pop(cursor_pos)
elif user_input == escape_code:
user_input = ord(getch())
if user_input == delete:
curr_chars.pop(cursor_pos)
elif user_input == left:
cursor_pos -= 1
elif user_input == right:
if cursor_pos < len(curr_chars):
cursor_pos += 1
elif user_input == home:
cursor_pos = 0
elif user_input == end:
cursor_pos = len(curr_chars)
elif user_input == ctrl_home:
curr_chars = curr_chars[cursor_pos:]
cursor_pos = 0
elif user_input == ctrl_end:
curr_chars = curr_chars[:cursor_pos]
cursor_pos = len(curr_chars)
elif user_input == ctrl_left:
try:
chars_left_of_cursor = "".join(curr_chars[:cursor_pos])
left_closest_space_char_index = [m.span()[0] for m in finditer(" \w", chars_left_of_cursor)][-1]
pos_diff = cursor_pos - left_closest_space_char_index - 1
cursor_pos -= pos_diff
except IndexError:
cursor_pos = 0
elif user_input == ctrl_right:
try:
chars_right_of_cursor = "".join(curr_chars[cursor_pos + 1:])
right_closest_space_char_index = [m.span()[0] for m in finditer(" \w", chars_right_of_cursor)][0]
cursor_pos += right_closest_space_char_index + 2
except IndexError:
cursor_pos = len(curr_chars) - 1
elif user_input != enter:
if cursor_pos > len(curr_chars) - 1:
curr_chars.append(char_g)
else:
curr_chars.insert(cursor_pos, char_g)
cursor_pos += 1
# clear entire line, write contents of curr_chars, reposition cursor
stdout.write("\r" + prev_len * " " + "\r")
stdout.write("".join(curr_chars))
pos_diff = len(curr_chars) - cursor_pos
stdout.write("\b" * pos_diff)
stdout.write("\r" + len(curr_chars) * " " + "\r")
stdout.write("".join(curr_chars) + "\n")
return "".join(curr_chars)
When I run the below program it does input verification correctly and it performs the Collatz Sequence just fine. The issue is that it doesn't loop back to the beginning. I have tried removing the "break" in the second part, I have tried moving the second block around, and other small stuff, but I can't get it to go back to the input again to start over.
#Collatz Sequence
import sys
#main part of input and processing number
print ('Collatz Sequence, Y\'all!')
try:
while True:
print ('Please type in an integer greater than 1. Type (q) to quit.')
number = input()
if number == 'q':
print ('OK, see ya!')
sys.exit() # quit the program
if number.isdecimal() == True: #checks that input is a number
number = int(number)
break #breaks out of loop
print ('Please type in a number')
while True:
maybe = number%2
#print ('DEBUG ' + 'maybe is ' + str (maybe) + ' number is ' + str (number))
if number == 1:
print (' ')
print (' ')
print ('Final answer is 1.')
print (' ')
print ('Let\'s do it again:')
print (' ')
break
elif maybe == 0:
print (' ')
print (str(number) + ' is even.')
number = number//2
elif maybe == 1:
print (' ')
print (str(number) + ' is odd.')
number = 3 * number + 1
print ('Recalculating')
except KeyboardInterrupt:
sys.exit()
Try making your logic simpler and you will see your problem. Your current logic is:
try:
while True:
<get number>
if <want to quit>: sys.exit()
if <number is good>: break
while True:
if <done>: break
<step>
except KeyboardInterrupt:
sys.exit()
It sounds like you want something more like
try:
while True:
while True:
<get number>
if <want to quit>: sys.exit()
if <number is good>: break
while True:
if <done>: break
<step>
except KeyboardInterrupt:
sys.exit()
You are confusing the fact that you use loops to get input and calculate the path with needing to use a loop to continue that process. Functions would make this much more obvious.
This question already has answers here:
How to stop the input function from inserting a new line?
(9 answers)
Closed 4 years ago.
Is it possible to remove the prompt and the text that the user typed when using input()? I am using cmd on Windows 10 and would prefer a solution that works cross platform, but I don't really mind.
First attempt
Using the code:
user_input = input("Enter some text: ")
print("You just entered " + user_input)
produces:
Enter some text: hello
You just entered hello
but I would like:
Enter some text: hello
and then:
You just entered hello
Second attempt
I've used the getpass module, but that hides what the user is typing because it is designed for passwords. I looked at the code for getpass2 here and found that it uses the getch() function from msvcrt. I tried using a similar method, but it did not work. This code:
import msvcrt
prompt = "Enter some text: "
user_input = ""
print(prompt, end="\r")
current_character = ""
while current_character != "\r":
current_character = msvcrt.getch()
user_input += str(current_character, "utf8")
print(prompt + user_input, end="\r")
print("You entered" + user_input)
produces this output:
Enter some text: h e l l o
and then when I press enter:
nter some text: h e l l o
It also allows the user to use the backspace key to delete the prompt.
Third attempt
I know I can use os.system("cls") to clear everything in the console, but this removes text that was in the console before. For example, this code:
import os
print("foo")
user_input = input("Enter some text: ")
os.system("cls")
print("You just entered " + user_input)
removes the foo that was printed to the console before the input. If what I'm asking isn't directly possible, is there a workaround that can save the text in the console to a variable, and then after the user input clear the console and reprint the text that was in the console?
This is definitely not the optimal solution;
However, in response to
is there a workaround that can save the text in the console to a
variable
, you could keep appending the required text to a variable, and re-print that each time, as you suggested. Again, I would not recommend this as your actual implementation, but while we wait for someone to come along with the correct approach...
import os
to_print = ""
to_print += "foo" + "\n"
print(to_print)
user_input = input("Enter some text: ")
os.system("cls")
to_print += "You just entered " + user_input + "\n"
print(to_print)
I have written an application in Python to work with strings, i made a menu prompt from which i can select an operation to do, i tested all the functions, they work well, except the menu and main functions, that when i enter my choice nothing happens. Here's the code:
import re
import os
def searchInFile(searched, file):
try:
f = open(file)
except IOError.strerror as e:
print("Couldn't open the file: ", e)
else:
sea = re.compile(searched, re.IGNORECASE)
for line in f:
if re.search(sea, line):
print(line, end='')
def validateWithPattern(string):
patt = re.compile('([a-z0-9-_.])+#([a-z]+.)([a-z]{2,3})', re.IGNORECASE)
if re.search(patt, string):
print("Valid")
else:
print("Not valid!")
def menu():
print("|================MENU=================|\n", end='')
print("|0- Exit the program |\n", end='')
print("|1- Validate mail address |\n", end='')
print("|2- Search a string in a file |\n", end='')
print("|=====================================|\n", end='')
b = input("->")
return b
def main():
b = 10
while b != 0:
b = menu()
if b == 1:
a = input('Enter you mail address: ')
validateWithPattern(a)
elif b == 2:
a = input('Enter the file name: ')
c = input('Enter the string: ')
searchInFile(c, a)
elif b == 0:
os.system("PAUSE")
else: print("Choice error")
if __name__ == "__main__":
main()
Your b variable you are returning from menu function is a string, not an integer, so you can't compare it with numbers (input is automatically saved as string). If you use return int(b) instead of return b, it will be ok.
Also, I think your else: print("Choice error") should be indented the same way your if and elif are, since you probably want to write "Choice error" only if b is not one of given choices. The way it is indented in your code will print "Choice error" after the while loop ends and it will not print that message if you input the value it can't recognize (for example 3).