I would like to understand how to reprint multiple lines in Python 3.5.
This is an example of a script where I would like to refresh the printed statement in place.
import random
import time
a = 0
while True:
statement = """
Line {}
Line {}
Line {}
Value = {}
""".format(random.random(), random.random(), random.random(), a)
print(statement, end='\r')
time.sleep(1)
a += 1
What I am trying to do is have:
Line 1
Line 2
Line 3
Value = 1
Write on top of / update / refresh:
Line 1
Line 2
Line 3
Value = 0
The values of each line will change each time. This is effectively giving me a status update of each Line.
I saw another question from 5 years ago however with the addition of the end argument in Python 3+ print function, I am hoping that there is a much simpler solution.
If you want to clear the screen each time you call print(), so that it appears the print is overwritten each time, you can use clear in unix or cls in windows, for example:
import subprocess
a = 0
while True:
print(a)
a += 1
subprocess.call("clear")
If I've understood correctly you're looking for this type of solution:
import random
import time
import os
def clear_screen():
os.system('cls' if os.name == 'nt' else 'clear')
a = 0
while True:
clear_screen()
statement = """
Line {}
Line {}
Line {}
Value = {}
""".format(random.random(), random.random(), random.random(), a)
print(statement, end='\r')
time.sleep(1)
a += 1
This solution won't work with some software like IDLE, Sublime Text, Eclipse... The problem with running it within this type of software is that clear/cls uses ANSI escape sequences to clear the screen. These commands write a string such as "\033[[80;j" to the output buffer. The native command prompt is able to interpret this as a command to clear the screen but these pseudo-terminals don't know how to interpret it, so they just end up printing small square as if printing an unknown character.
If you're using this type of software, one hack around could be doing print('\n' * 100), it won't be the optimal solution but it's better than nothing.
You could use curses for this.
#!/usr/bin/python3
import curses
from time import sleep
from random import random
statement = """
Line {}
Line {}
Line {}
Value = {}"""
screen = curses.initscr()
n = 0
while n < 20:
screen.clear()
screen.addstr(0, 0, statement.format(random(), random(), random(), n))
screen.refresh()
n += 1
sleep(0.5)
curses.endwin()
Related
I want to paint some special words while the program is getting them , actually in real-time .
so I've wrote this piece of code which do it quite good but i still have problem with changing the location of the pointer with move keys on keyboard and start typing from where i moved it .
can anyone give me a hint how to do it ?
here is the CODE :
from colorama import init
from colorama import Fore
import sys
import msvcrt
special_words = ['test' , 'foo' , 'bar', 'Ham']
my_text = ''
init( autoreset = True)
while True:
c = msvcrt.getch()
if ord(c) == ord('\r'): # newline, stop
break
elif ord(c) == ord('\b') :
sys.stdout.write('\b')
sys.stdout.write(' ')
my_text = my_text[:-1]
#CURSOR_UP_ONE = '\x1b[1A'
#ERASE_LINE = '\x1b[2K'
#print ERASE_LINE,
elif ord(c) == 224 :
set (-1, 1)
else:
my_text += c
sys.stdout.write("\r") # move to the line beginning
for j, word in enumerate(my_text.split()):
if word in special_words:
sys.stdout.write(Fore.GREEN+ word)
else:
sys.stdout.write(Fore.RESET + word)
if j != len(my_text.split())-1:
sys.stdout.write(' ')
else:
for i in range(0, len(my_text) - my_text.rfind(word) - len(word)):
sys.stdout.write(' ')
sys.stdout.flush()
Doing it the easy way
As you already seem to be using the colorama module, the most easy and portable way to position the cursor should be to use the corresponding ANSI controlsequence (see: http://en.m.wikipedia.org/wiki/ANSI_escape_code)
The one you are looking for should be CUP – Cursor Position (CSI n ; m H)positioning the cursor in row n and column m.
The code would look like this then:
def move (y, x):
print("\033[%d;%dH" % (y, x))
Suffering by doing everything by hand
The long and painful way to make things work even in a windows console, that doesn't know about the above mentioned control sequence would be to use the windows API.
Fortunately the colorama module will do this (hard) work for you, as long as you don't forget a call to colorama.init().
For didactic purposes, I left the code of the most painful approach leaving out the functionality of the colorama module, doing everything by hand.
import ctypes
from ctypes import c_long, c_wchar_p, c_ulong, c_void_p
#==== GLOBAL VARIABLES ======================
gHandle = ctypes.windll.kernel32.GetStdHandle(c_long(-11))
def move (y, x):
"""Move cursor to position indicated by x and y."""
value = x + (y << 16)
ctypes.windll.kernel32.SetConsoleCursorPosition(gHandle, c_ulong(value))
def addstr (string):
"""Write string"""
ctypes.windll.kernel32.WriteConsoleW(gHandle, c_wchar_p(string), c_ulong(len(string)), c_void_p(), None)
As already stated in the comment section this attempt still leaves you with the problem, that your application will only work in the named console, so maybe you will still want to supply a curses version too.
To detect if curses is supported or you will have to use the windows API, you might try something like this.
#==== IMPORTS =================================================================
try:
import curses
HAVE_CURSES = True
except:
HAVE_CURSES = False
pass
In the program I've been working on in Python, I need to be able to print a list of elements one by one, going to a new line after n elements to form a grid. However, every time the program reprints the grid, you can see it progressing element by element, which looks rather ugly and distracting to the user. I was wondering if there was a way to "pause" the console output for a brief amount of time to allow the grid to be printed, then show the grid afterwards, erasing the previous printout, as to not show it printing element by element. The reason I need to do this is because the program uses Colorama for colored outputs, but different elements in the list will need to have different colors, meaning each element has to be printed one by one.
EDIT (Current code):
import time as t
from os import system as c
h = 50
w = 50
loop1 = 0
ostype = "Windows"
def cl():
if(ostype == "Linux"):
c('clear')
if(ostype == "Windows"):
c('cls')
def do():
grid = []
for x in range(0,h):
temp = []
for z in range(0,w):
temp.append("#")
grid.append(temp)
for a in range(0,h):
for b in range(0,w):
print(grid[a][b], flush=False, end="")
print()
while(loop1 == 0):
do()
t.sleep(1)
cl()
You can probably tell print to not to flush the standard out buffer, and have the last print to flush everything. Depends on what version of python you're using, for python 3 print function takes a flush argument, set that to true/false accordingly.
I am running a program that works in parallel, utilizing the Pool object from the multiprocessing module.
What I am trying to do is run a function n number of times in parallel, each having a separate loading %, and I would like it to be updating the percentage for each function without replacing other percentages... example:
f(x):
while x < 0:
print 'For x = {0}, {1}% completed...\r'.format(x, percentage),
And I would run the function multiple times in parallel.
The effect I am trying to achieve is the following, for f(10000000), f(15000000), f(7000000):
For x = 10000000, 43% completed
For x = 15000000, 31% completed
For x = 7000000, 77% completed
And the percentages will be updating in their individual lines without replacing for other values of x, in this function f which will be running three times at the same time.
I tried using the carriage return '\r' but that replaces every line and just creates a mess.
Thanks for taking the time to read this post! I hope you can tell me.
I am using Python 2.7 but if it can only be achieved with Python 3 I am open to suggestions.
Curses
As #Keozon mentioned in the comments, one way to achieve this would be to use the curses library.
There is a good guide for curses on the python website.
ANSI Escape Codes
Alternatively, you might try using ANSI escape codes to move the cursor around.
This is in Python3, but it'll work just fine in any version, you'll just need to change the print statements around (or from __future__ import print_function).
print('Hello')
print('World')
print('\033[F\033[F\033[K', end='') # Up, Up, Clear line
# Cursor is at the 'H' of 'Hello'
print('Hi') # Overwriting 'Hello'
# Cursor is at the 'W' of 'World'
print('\033[E', end='') # Down
# Cursor is on the blank line after 'World'
print('Back to the end')
Output:
Hi
World
Back to the end
Edit:
I've done way too much work for you here, but hey, here's basically a full solution using the ANSI method I mentioned above:
import time
import random
class ProgressBar:
def __init__(self, name):
self._name = name
self._progress = 0
#property
def name(self):
return self._name
def get_progress(self):
"""
Randomly increment the progress bar and ensure it doesn't go
over 100
"""
self._progress += int(random.random()*5)
if self._progress > 100:
self._progress = 100
return self._progress
class MultipleProgressBars:
def __init__(self, progress_bars):
self._progress_bars = progress_bars
self._first_update = True
self._all_finished = False
#property
def all_finished(self):
"""
A boolean indicating if all progress bars are at 100
"""
return self._all_finished
def update(self):
"""
Update each progress bar
"""
# We don't want to move up and clear a line on the first run
# so we have a flag to make sure this only happens on later
# calls
if not self._first_update:
# Move up and clear the line the correct number of times
print('\033[F\033[K'*len(self._progress_bars),end='', sep='')
num_complete = 0 # Number of progress bars complete
for progress_bar in self._progress_bars:
name = progress_bar.name
progress = progress_bar.get_progress()
if progress == 100:
num_complete += 1
# Print out a progress bar (scaled to 40 chars wide)
print(
name.ljust(10),
'[' + ('='*int(progress*0.4)).ljust(40) + ']',
str(progress)+'%')
if num_complete == len(self._progress_bars):
self._all_finished = True
self._first_update = False # Mark the first update done
# Create a list of ProgressBars and give them relevant names
progress_bars = [
ProgressBar('James'),
ProgressBar('Bert'),
ProgressBar('Alfred'),
ProgressBar('Frank')
]
# Create a new instance of our MultipleProgressBars class
mpb = MultipleProgressBars(progress_bars)
# Keep updating them while at least one of them is still active
while not mpb.all_finished:
mpb.update()
time.sleep(0.2)
I am very new in Python and I decided to make a game.
I want a value to be output like this:
Heat: x #x would always be changing
For that I have the following block of code:
while True:
print("Heat: {}".format(Heat))
but all it does is spam "Heat: xHeat: xHeat: x"
When it should be only one Heat bar
What should I do?
In that code 'Heat' in the loop and it will be printed all the time:
Heat = 0
while True:
Heat +=1
print ('Heat: {heat}'.format(heat=Heat))
In that code 'Heat' out of the loop and it will be printed once:
Heat = 0
print ('Heat:')
while True:
Heat +=1
print ('{heat}'.format(heat=Heat))
if you want more newlines use '\n' char (strictly depends on OS).
You can use carriage return to send the cursor to the start of the line.
import sys
while True:
sys.stdout.write("\rHeat: {}".format(Heat))
sys.stdout.flush()
But this approach doesn't sound like you will be able to extend it into any sort of game.
You should look up the python curses library for complete control over the console output.
Also if the number of digits in your output changes then you might want to right-align the output so that you don't get any left-overs. This code demonstrates what happens if you go from a 2 digit number to a 1 digit number:
import sys
import time
for heat in reversed(range(5, 12)):
time.sleep(0.5)
sys.stdout.write("\rHeat: {:>5}".format(heat))
sys.stdout.flush()
I'm having some trouble here. For my CS assignment, I have to have python take data from a file on my pc and run the data through my program.
So, this code works fine on http://repl.it/languages/Python, but not in python. I'm assuming because my line of code has some Python 2.0 lines of code? I can't seem to fix it. Can you guys help? And, another small question except this one. I have to input some code in my program to take data from a file and run it through my program as I stated above. I have this.
import math
def mean(values):
average = sum(values)*1.0/len(values)
return average
def deviation(values):
length = len(values)
m = mean(values)
total_sum = 0
for i in range(length):
total_sum += (values[i]-m)**2
root = total_sum*1.0/length
return math.sqrt(root)
def median(values):
if len(values)%2 != 0:
return sorted(values)[len(values)/2]
else:
midavg = (sorted(values)[len(values)/2] + sorted(values)[len(values)/2-1])/2.0
return midavg
def main():
x = [15, 17, 40, 16, 9]
print mean(x)
print deviation(x)
print median(x)
main()
How do I specifically have the program take data from the file and run it through my program? The data is just a bunch of numbers, by the way. It's been giving me trouble for some hours now. Thanks if you can help out.
This is what I know about the opening/closing file stuff so far
f = open("filename.txt")
data = f.readlines()
f.close()
Apparently you are using python2.x:
I'm assuming because my line of code has some Python 2.0 lines of code?
So yes, you do have a problem: In python3.x, print became a function.
Thus, your prints need to be changed:
print mean(x)
print deviation(x)
print median(x)
Becomes
print(mean(x))
print(deviation(x))
print(median(x))
Also, your part about opening and closing files is unclear.