I am very new to Python and I would like to know how I would clear a text that has been printed and add another piece of text. For example, I would like to display "Hello" then program with a delay of 10 seconds to replace text with another text "Goodbye". I am using Python 3.3 on Windows 7.
import time
import os
print ('hello there')
time.sleep(10) # this will BLOCK your program for 10 seconds
os.system('cls') # clear the screen, since cls is the clear screen command for windows
print ('bye')
input() # this is to wait to user to enter something to exist
version 2, using some 'visual' effects :D
import time
import os
print ('hello there')
for i in range(1, 10):
time.sleep(1)
print ('.')
os.system('cls')
print ('bye')
input()
Once text is sent to stdout, there really isn't a good way to change it. What you probably want to do would require a UI library such as tkinter (which comes with Python) or wxPython. Then you can create a Window with a label widget that can change every few seconds. You might be able to use Python's curses library too, but I have yet to see a coherent tutorial on how you would use that for this sort of thing.
Python's output is based on an abstraction of "output is just a file that you can write to", so there's no way to do this cross-platform.
However, if you want it to work in a Windows cmd.exe console (aka "DOS prompt"), and don't care about working inside IDLE, on Unix, over a network, etc., you can use the MSVCRT console I/O APIs.
Unfortunately, the limited set of console I/O APIs built into the standard library doesn't include the clear function. But you can look for third-party extended console I/O libraries on PyPI, or use PyWin32 to call the MSVCRT functions directly.
Or you can use a cheap hack:
import subprocess
subprocess.check_call(['cls'])
This just calls the cls function, which does everything for you.
Related
This question already has answers here:
How to flush the input stream?
(4 answers)
Closed 1 year ago.
I'm making a game that runs on the console in python. When I exit the game, all the keys I pressed are automatically typed. How do I stop this from happening? Also, I still want to have user input when I use the input() function. This is on Windows by the way.
If you want the code, this has the same "problem":
for _ in range(100000):
print("Hello")
When the program finishes in the command prompt, this comes up:
C:\Users\User>awdsaawdsadwsaasdwaws
Basically, whatever keys were pressed while the code was running. This happens when other things run in the command prompt too, but I want to know how to disable it in python.
Edit: I kept digging and found that what I was looking for was flushing or clearing keyboard buffer. I marked my question as a duplicate of another which has a few answers, but this one worked best for me:
def flush_input():
try:
import msvcrt
while msvcrt.kbhit():
msvcrt.getch()
except ImportError:
import sys, termios #for linux/unix
termios.tcflush(sys.stdin, termios.TCIOFLUSH)
This happens because your computer registers the key strokes and on the console, those are made available on the stdin input stream.
If you save your script as test.py and run python test.py and start entering some keystrokes, like abc, those letters will be on standard input.
Your script doesn't read them, because it doesn't touch that stream, as you're not using input() or any other calls that would read that stream. So your script finishes, the characters are still on standard input, the prompt comes back and it reads those characters, with the given result:
Hello
Hello
Hello
PS C:\Users\username> abc
To avoid this, you can read / flush the input buffer at the end of your script. However, this is surprisingly hard if you need it to work across all operating systems and in different modes of running your script (directly from cmd, IDLE, in other IDEs, etc.)
The problem is there's no way to know if there's input on the standard input stream, until you try to read from it. But if you try to read from it, your script will pause until an 'end of line' or 'end of file' is received. And if the user is just hitting keys, that won't happen, so you'll end up reading until they hit something like Ctrl+Break or Ctrl+C.
Here's a way I think is relatively robust, but I recommend you test it in scenarios and environments you consider likely for use of your script:
import sys
import threading
import queue
import os
import signal
for _ in range(100000):
print("Hello")
timeout = 0.1 # sec
def no_input():
# stop main thread (which is probably blocked reading input) via an interrupt signal
# only available for windows in Python version 3.2 or higher
os.kill(os.getpid(), signal.SIGINT)
exit()
# if a sigint is received, exit the main thread (you could call another function to do work first and then exit()
signal.signal(signal.SIGINT, exit)
# input is stored here, until it's dealt with
input_queue = queue.Queue()
# read all available input until main thread exit
def get_input():
while True:
try:
# read input, not doing anything with it
_ = input_queue.get(timeout=timeout)
except queue.Empty:
no_input()
reading_thread = threading.Thread(target=get_input)
reading_thread.start()
# main loop: put any available input in the queue, will wait for input if there is none
for line in sys.stdin:
input_queue.put(line)
# wait for reading thread
reading_thread.join()
It basically reads the input from a second thread, allowing that the main thread to get the input and possibly do something with it until there's nothing left and then it just tells the main thread to exit. Note that this will result in your script exiting with an exit code of 2, which may not be what you want.
Also note that you'll still see the input on screen, but it will no longer be passed to the terminal:
Hello
Hello
Hello
abc
PS C:\Users\username>
I don't know if there's an easy way to avoid the echo, other than on Linux doing something like stty -echo. You could of course just call the system to clear the screen at the end of your script:
from subprocess import call
from os import name as os_name
call('clear' if os_name =='posix' else 'cls')
I know you can clear the shell by executing clear using os.system, but this way seems quite messy to me since the commands are logged in the history and are litterally interpreted as commands run as the user to the OS.
I'd like to know if there is a better way to clear the output in a commandline script?
print "\033c"
works on my system.
You could also cache the clear-screen escape sequence produced by clear command:
import subprocess
clear_screen_seq = subprocess.check_output('clear')
then
print clear_screen_seq
any time you want to clear the screen.
tput clear command that produces the same sequence is defined in POSIX.
You could use curses, to get the sequence:
import curses
import sys
clear_screen_seq = b''
if sys.stdout.isatty():
curses.setupterm()
clear_screen_seq = curses.tigetstr('clear')
The advantage is that you don't need to call curses.initscr() that is required to get a window object which has .erase(), .clear() methods.
To use the same source on both Python 2 and 3, you could use os.write() function:
import os
os.write(sys.stdout.fileno(), clear_screen_seq)
clear command on my system also tries to clear the scrollback buffer using tigetstr("E3").
Here's a complete Python port of the clear.c command:
#!/usr/bin/env python
"""Clear screen in the terminal."""
import curses
import os
import sys
curses.setupterm()
e3 = curses.tigetstr('E3') or b''
clear_screen_seq = curses.tigetstr('clear') or b''
os.write(sys.stdout.fileno(), e3 + clear_screen_seq)
You can use the Python interface to ncurses, specifically window.erase and window.clear.
https://docs.python.org/3.5/library/curses.html
I use 2 print statements to clear the screen.
Clears the screen:
print(chr(27) + "[2J")
Moves cursor to begining row 1 column 1:
print(chr(27) + "[1;1f")
I like this method because you can move the cursor anywhere you want by [<row>;<col>f
The chr(27) is the escape character and the stuff in quotes tells the terminal what to do.
I have a python script which will give an output file. I need to feed this output file to a command line program. Is there any way I could call the commandline program and control it to process the file in python?
I tried to run this code
import os
import subprocess
import sys
proc = subprocess.Popen(["program.exe"], stdin=subprocess.PIPE)
proc.communicate(input=sys.argv[1]) #here the filename should be entered
proc.communicate(input=sys.argv[2]) #choice 1
proc.communicate(input=sys.argv[3]) #choice 2
is there any way I could enter the input coming from the commandline. And also though the cmd program opens the interface flickers after i run the code.
Thanks.
Note: platform is windows
Have a look at http://docs.python.org/library/subprocess.html. It's the current way to go when starting external programms. There are many examples and you have to check yourself which one fits your needs best.
You could do os.system(somestr) which lets you execute semestr as a command on the command line. However, this has been scrutinized over time for being insecure, etc (will post a link as soon as I find it).
As a result, it has been conventionally replaced with subprocess.popen
Hope this helps
depending on how much control you need, you might find it easier to use pexpect which makes parsing the output of the program rather easy and can also easily be used to talk to the programs stdin. Check out the website, they have some nice examples.
If your target program is expecting the input on STDIN, you can redirect using pipe:
python myfile.py | someprogram
As I just answered another question regarding subprocess, there is a better alternative!
Please have a look at the great library python sh, it is a full-fledged subprocess interface for Python that allows you to call any program as if it were a function, and more important, it's pleasingly pythonic.
Beside redirecting data stream with pipes, you can also process a command line such as:
mycode.py -o outputfile inputfilename.txt
You must import sys
import sys
and in you main function:
ii=1
infile=None
outfile=None
# let's process the command line
while ii < len(sys.argv):
arg = sys.argv[ii]
if arg == '-o':
ii = ii +1
outfile = sys.argv[ii]
else:
infile=arg
ii = ii +1
Of course, you can add some file checking, etc...
Short Question
Is it possible/practical to write and update a multi-line (contains \n) string on a Windows terminal?
Background
I have looked into curses, but it is Unix only. I saw a few other Window ports, but it was a bit troubling that Windows XP was an experimental OS for one them. I am hoping to use this as part of a diagnostic feature to display link status, message rates, etc on a mainly terminal application (note that some variants do have a wxPython GUI input). That being said, using Cygwin is non-ideal and would love to find a workaround using only the sys module.
I have tried the following: (note that I expected them to fail, but hoped I would be wrong)
Attempt 1: Updates the string but it is all on 1 line
sys.stdout.write("\r")
sys.stdout.write("This is a multi-line screen print test")
sys.stdout.write("Line 1")
sys.stdout.write("Line 2")
sys.stdout.flush()
Attempt 2: Does not update but prints all the lines
sys.stdout.write("\r")
sys.stdout.write("This is a multi-line screen print test\n")
sys.stdout.write("Line 1 \n")
sys.stdout.write("Line 2\n")
sys.stdout.flush()
The closest thing I could find to curses (that has been updated in the last 10 years) was Windows Console Driver. Rather than use this approach I went at it was a less elegant method.
import os
import time
while(1):
time.sleep(.05)
os.system('cls')
print "This is a multi-line screen print test"
print "Line 1"
print "Line 2"
You might have to use the Windows Console API. For example, SetConsoleCursorPosition. Other people appear to have implemented Python modules to support this API: 1, 2
I am running command-line Python scripts from the Windows taskbar by having a shortcut pointing to the Python interpreter with the actual script as a parameter.
After the script has been processed, the interpreter terminates and the output window is closed which makes it impossible to read script output.
What is the most straightforward way to keep the interpreter window open until any key is pressed?
In batch files, one can end the script with pause. The closest thing to this I found in python is raw_input() which is sub-optimal because it requires pressing the return key (instead of any key).
One way is to leave a raw_input() at the end so the script waits for you to press Enter before it terminates.
Try os.system("pause") — I used it and it worked for me.
Make sure to include import os at the top of your script.
There's no need to wait for input before closing, just change your command like so:
cmd /K python <script>
The /K switch will execute the command that follows, but leave the command interpreter window open, in contrast to /C, which executes and then closes.
The best option: os.system('pause') <-- this will actually display a message saying 'press any key to continue' whereas adding just raw_input('') will print no message, just the cursor will be available.
not related to answer:
os.system("some cmd command") is a really great command as the command can execute any batch file/cmd commands.
One way is to leave a raw_input() at the end so the script waits for you to press enter before it terminates.
The advantage of using raw_input() instead of msvcrt.* stuff is that the former is a part of standard Python (i.e. absolutely cross-platform). This also means that the script window will be alive after double-clicking on the script file icon, without the need to do
cmd /K python <script>
On Windows you can use the msvcrt module.
msvcrt.kbhit()
Return True if a keypress is waiting to be read.
msvcrt.getch()
Read a keypress and return the resulting character as a byte string. Nothing is echoed to the console. This call will block if a keypress is not already available, but will not wait for Enter to be pressed. If the pressed key was a special function key, this will return '\000' or '\xe0'; the next call will return the keycode. The Control-C keypress cannot be read with this function.
If you want it to also work on Unix-like systems you can try this solution using the termios and fcntl modules.
As to the "problem" of what key to press to close it, I (and thousands of others, I'm sure) simply use input("Press Enter to close").
There's a simple way to do this, you can use keyboard module's wait function. For example, you can do:
import keyboard
print("things before the pause")
keyboard.wait("esc") # esc is just an example, you can obviously put every key you want
print("things after the pause")
Getting python to read a single character from the terminal in an unbuffered manner is a little bit tricky, but here's a recipe that'll do it:
Recipe 134892: getch()-like unbuffered character reading from stdin on both Windows and Unix (Python)
On Windows 10 insert at beggining this:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
Strange, but it works for me! (Together with input() at the end, of course)
An external WConio module can help here: http://newcenturycomputers.net/projects/wconio.html
import WConio
WConio.getch()
import pdb
pdb.debug()
This is used to debug the script. Should be useful to break also.
If you type
input("")
It will wait for them to press any button then it will continue. Also you can put text between the quotes.