I want to replace the cmd output of my Python script, without overwriting the first three characters of the line. Here is what I mean:
How I want it:
>>>ID1 downloading
>>>ID1 converting
>>>ID1 finished
With /r:
>>>ID0 downloading
>>>converting
>>>finished
This isn't fundamentally a Python question; it's a standard output question.
The standard output doesn't work that way. The simplest thing is to just rewrite "ID1".
Otherwise you will need to move to something more advanced: either console-specific formatting commands (like ANSI), or a library like curses.
Try this. But this may not work in IDLE.
from time import sleep
from sys import stdout
stdout.write("\r%s" % "ID1 downloading")
stdout.flush()
sleep(1)
stdout.write("\r%s" % "ID1 converting ")
stdout.flush()
sleep(1)
stdout.write("\r%s" % "ID1 done ")
stdout.write("\r \r\n") # clean up
Related
I have the following very simple code
stdout.write("Hello World")
stdout.write("\rBye world")
stdout.write("\rActually hello back")
Which prints as expected 'Actually hello back' however if i were to add a newline
stdout.write("\n")
How can I go back a newline and then to the beginning of the line so I can actually just output "Hi" instead of
Actually hello back
Hi
I tried
stdout.write("\r")
stdout.write("\b")
However none of them seem to do the trick. The end goal is to display a big chunk of text and then update the output in real time without having to write again. How can I achieve this in python?
EDIT
My question is different than the one suggested as I don't want to modify a single line. I want to be able to print 4-5 lines of text and then replace them in real time instead of just one line that is modified.
Well, if You want to gain full control over the terminal, I would suggest to use the curses library.
The curses module provides an interface to the curses library, the
de-facto standard for portable advanced terminal handling.
Using it, You can edit multiple lines in terminal like this:
import curses
import time
stdscr = curses.initscr()
stdscr.addstr("line 1\n")
stdscr.addstr("line 2\n")
stdscr.refresh()
time.sleep(3)
stdscr.erase()
stdscr.addstr("edited line 1\n")
stdscr.addstr("edited line 2\n")
stdscr.refresh()
time.sleep(3)
curses.endwin()
The capabilities of this library are much greater though. Full tutorial here.
I'm trying to make a percentage text that displays a progress amount but i'm trying to avoid the percentages printing out like this:
Progress: 10%
Progress: 11%
Progress: 12%
Progress: 13%
How can erase and write over the current line? Iv'e tried using the \r and \b characters but neither seems to work. Every single thing I found before has been for either for Python 2 or Unix so i'm not even sure which of those is the problem (if even one of them) because i'm not using either. Does anyone know how I can do this with Python 3 running Windows 7? This is the unworking code that I have currently, but I've tried plenty of other things.
print('Progress: {}%'.format(solutions//possibleSolutions),flush=True,end="\r")
EDIT:
This is not a problem if I'm executing the program from command prompt so I don't think it is a problem with windows. I tried updating Python from what i was using previously (3.4.1) to the latest v3.4.3 and the issue is the same.
Heres a screenshot of the problem:
This is the best I can do at taking a screenshot of the issue. It appears as if each time I move the cursor farther to the left (passed one of the Progress:'s) that the gray area between the text and the cursor gets larger
EDIT 2: The problem is that IDLE does not support ASCII control codes. Solution: Use a different IDE.
You can use print:
print('Progress: {}%'.format(solutions),flush=True,end="\r")
You can't use '\r' and '\b' in IDLE. If you want to use it, try adding these lines at the start of your program:
import sys
sys.stdout = sys.__stdout__
and running idle with this batch script:
#echo off
echo Running IDLE...
py -m idlelib
then, you see output in cmd window and there are '\r' and '\b'.
Use the character '\r' for the print function. Default is '\n'.
'\r' stands for carriage return, '\n' means new line.
You can create a new class called Printer like this:
class Printer():
def __init__(self, data):
sys.stdout.write("\r\x1b[K"+data.__str__())
sys.stdout.flush()
Then, let's say you want to print the progress of a for loop:
for i in range(0, 100):
p = i * 100
output = "%d%% of the for loop completed" % p
Printer(output)
This is my first time asking a question. I am just starting to get into programming, so i am beginning with Python. So I've basically got a random number generator inside of a while loop, thats inside of my "r()' function. What I want to do is take all of the numbers (basically like an infinite amount until i shut down idle) and put them into a text file. Now i have looked for this on the world wide web and have found solutions for this, but on a windows computer. I have a mac with python 2.7. ANY HELP IS VERY MUCH APPRECIATED! My current code is below
from random import randrange
def r():
while True:
print randrange(1,10)
The general idea is to open the file, write to it (as many times as you need to), and close it. This is explained in the tutorial under Reading and Writing Files.
The with statement (described toward the end of that section) is a great way to make sure the file always gets closed. (Otherwise, when you stopped your script with ^C, the file might end up missing the last few hundred bytes, and you'd have to use try/finally to handle that properly.)
The write method on files isn't quite as "friendly" as the print statement—it doesn't automatically convert things to strings, add a newline at the end, accept multiple comma-separated values, etc. So usually, you'll want to use string formatting to do that stuff for you.
For example:
def r():
with open('textfile.txt', 'w') as f:
while True:
f.write('{}\n'.format(randrange(1, 10)))
You'll need to call the function and then redirect the output to a file or use the python API to write to a file. Your whole script could be:
from random import randrange
def r():
while True:
print randrange(1,10)
r()
Then you can run python script_name.py > output.txt
If you'd like to use the python API to write to a file, your script should be modified to something like the following:
from random import randrange
def r():
with open('somefile.txt', 'w') as f:
while True:
f.write('{}\n'.format(randrange(1,10)))
r()
The with statement will take care of closing the file instance appropriately.
I have a script which executes some command using os.popen4. Problem is some time command being executed will require user input ("y" or "n"). I am reading stdout/stderr and printing it, but it seems question from command doesn't got printed and it hangs. To make it work, i had to write "n" to stdin blindly. Can some one please guide on how to handle it?
Code not working:
(f_p_stdin, f_p_stdout_stderr) = os.popen4(cmd_exec,"t")
cmd_out = f_p_stdout_stderr.readlines()
print cmd_out
f_p_stdin.write("n")
f_p_stdin.close()
f_p_stdout_stderr.close()
Working Code:
(f_p_stdin, f_p_stdout_stderr) = os.popen4(cmd_exec,"t")
cmd_out = f_p_stdout_stderr.readlines()
f_p_stdin.write("n")
f_p_stdin.close()
print cmd_out
f_p_stdout_stderr.close()
NOTE : I am aware that it is depreciated and subprocess module is used, but right now i don't know on how to use it. So i'll appreciate if some one will help me to handle it using os.popen4. I want to capture the question and handle the input from user and execute it.
readlines() : returns a list containing all the lines of data in the file. If reading from a process like in this case, there is a good chance it does not send a newline and/or flush the output. You should read characters from the input and process that to see if the question was posed.
It would help to know what cmd_exec looks like, so others can try and emulate what you tried.
Update:
I wrote a uncheckout command in Python:
#! /usr/bin/env python
# coding: utf-8
import sys
print 'Uncheckout of {} is irreversible'.format(sys.argv[1])
print 'Do you want to proceed? [y/N]',
sys.stdout.flush()
x = raw_input()
if x == 'y':
print sys.argv[1], "no longer checked out"
else:
print sys.argv[1], "still checked out"
I put the prompt string on purpose not as argument to raw_input, to be able to do the flush() explicitly.
Neither of your code snippets work with that (assuming cmd_exec to be ['./uncheckout', 'abc.txt'] or './uncheckout abc.txt', popen4() uses the shell in the latter case to start the program).
Only when I move the readlines() until after the write() and close() will the command continue.
That makes sense to me as the close() flushes the output. You are writing in text mode and that buffers normally until end-of-line, which is not in your .write('n').
To be able to check what the prompt is and test and react on that., the following works with the above uncheckout:
#! /usr/bin/env python
# coding: utf-8
import os
import sys
cmd_exec = ['./uncheckout', 'abc.txt']
(f_p_stdin, f_p_stdout_stderr) = os.popen4(cmd_exec,"t")
line = ''
while True:
x = f_p_stdout_stderr.read(1)
if not x:
break
sys.stdout.write(x)
sys.stdout.flush()
if x == '\n':
line = ''
else:
line += x
if line.endswith('[y/N]'):
f_p_stdin.write("n\n")
f_p_stdin.flush()
sys.stdout.write('\n')
Maybe you can work backwards from that to make something that works for you. Make sure to keep flushes at appropriate places.
I have a program that grabs some data through ssh using paramiko:
ssh = paramiko.SSHClient()
ssh.connect(main.Server_IP, username=main.Username, password=main.Password)
ssh_stdin_host, ssh_stdout_host, ssh_stderr_host =ssh_session.exec_command(setting.GetHostData)
I would like to remove the first 4 lines from ssh_stdout_host. I've tried using StringIO to use readlines like this:
output = StringIO("".join(ssh_stdout_host))
data_all = output.readlines()
But I'm lost after this. What would be a good approach? Im using python 2.6.5. Thanks.
How to remove lines from stdout in python?
(this is a general answer for removing lines from the stdout Python console window, and has nothing to do with specific question involving paramiko, ssh etc)
see also: here and here
Instead of using the print command or print() function, use sys.stdout.write("...") combined with sys.stdout.flush(). To erase the written line, go 'back to the previous line' and overwrite all characters by spaces using sys.stdout.write('\r'+' '*n), where n is the number of characters in the line.
a nice example says it all:
import sys, time
print ('And now for something completely different ...')
time.sleep(0.5)
msg = 'I am going to erase this line from the console window.'
sys.stdout.write(msg); sys.stdout.flush()
time.sleep(1)
sys.stdout.write('\r' + ' '*len(msg))
sys.stdout.flush()
time.sleep(0.5)
print('\rdid I succeed?')
time.sleep(1)
edit
instead of sys.stdout.write(msg); sys.stdout.flush(), you could also use
print(msg, end='')
For Python versions below 3.0, put from __future__ import print_function at the top of your script/module for this to work.
Note that this solution works for the stdout Python console window, e.g. run the script by right-clicking and choosing 'open with -> python'. It does not work for SciTe, Idle, Eclipse or other editors with incorporated console windows. I am waiting myself for a solution for that here.
readlines provides all the data
allLines = [line for line in stdout.readlines()]
data_no_firstfour = "\n".join(allLines[4:])