Python 3 Print Update on multiple lines - python

Is it possible to print and update more than one line?
This works for one line:
print ("Orders: " + str(OrderCount) + " Operations: " + str(OperationCount), end="\r")
and get this: (Of course the numbers update because its in a loop)
Orders: 25 Operations: 300
I have tried this:
print ("Orders: " + str(OrderCount) + "\rOperations: " + str(OperationCount), end="\r\r")
and get this: (The number does update correctly)
Operations: 300
Looking for two lines that are updated like:
Orders: 25
Operations: 300
and not:
Orders: 23
Operations: 298
Orders: 24
Operations: 299
Orders: 25
Operations: 300

\r is a carriage return, where the cursor moves to the start of the line (column 0). From there, writing more text will overwrite what was written before, so you end up only with the last line (which is long enough to overwrite everything you've written before).
You want \n, a newline, which moves to the next line (and starts at column 0 again):
print("Orders: " + str(OrderCount) + "\nOperations: " + str(OperationCount), end="\n\n")
Rather than use str() and + concatenation, consider using string templating with str.format():
print("Orders: {}\nOperations: {}\n".format(OrderCount, OperationCount))
or a formatted string literal:
print(f"Orders: {OrderCount}\nOperations: {OperationCount}\n")
If you wanted to use \r carriage returns to update two lines, you could use ANSI control codes; printing \x1B[2A (ESC [ 2 A) moves the cursor up 2 times, adjust the number as needed. Whether or not this works depends on what platform you are supporting.
On my Mac, the following demo works and updates the two lines with random numbers; I used the ESC [ 0 K to make sure any remaining characters on the line are erased:
import random, time
orders = 0
operations = 0
UP = "\x1B[3A"
CLR = "\x1B[0K"
print("\n\n") # set up blank lines so cursor moves work
while True:
orders += random.randrange(1, 3)
operations += random.randrange(2, 10)
print(f"{UP}Orders: {orders}{CLR}\nOperations: {operations}{CLR}\n")
time.sleep(random.uniform(0.5, 2))
Demo:
You could also switch to a full-terminal control with Curses or stick to putting everything on one line. If you are going to go the Curses route, take into account that Windows compatibility is sketchy at best.

You probably want \n instead of \r. \r is "carriage return", a.k.a. "go back to the beginning of the line" -- so you're print "Operations" over "Orders".

Related

Python print to stay on same line [duplicate]

This question already has answers here:
How to overwrite the previous print to stdout?
(18 answers)
Closed last month.
import os
import time
h = 0
s = 0
m = 0
while s <= 60:
os.system('clear')
print h, "hours", m, 'minutes', s, 'seconds'
time.sleep(1)
s += 1
if s == 60:
m += 1
s = 0
elif m == 60:
h += 1
m = 0
s = 0
I have this code above. It all works fine and does what it is meant to do, but I want to make it so that it prints all the statements in the same line. For example, it should print out 0 hours 0 minutes 0 seconds and then on the same line should print out 0 hours 0 minutes 1 second, with the second variable the only thing that is changing. How do I do this? I have already tried using the os.system('clear') command but it does not work. Im running this on Mac OSX 10.7.
You should use what your terminal provides. In most cases you need to use '\r' (carriage return, return to first column in that line); but depending on the operating system this might be interpreted such that it also appends a line feed. I feel I remember that OSX might do this.
Also you need to avoid the automatic newline print will always append. You could use a trailing comma for this, but this has issues (stray space, no flushing). So I propose to use sys.stdout.write() instead and because without a newline typically no flushing will be done, you should use sys.stdout.flush() explicitly as well.
Then, returning to the first column will not delete the old output, so it only gets overwritten by the next line. If that is shorter than the one before, you will have trailing junk. To avoid this, again use what your terminal provides (very often '\x1b[K' erases everything till the end of the line without moving the cursor, but if this does not work for you, just print some spaces or make sure your output is formatted always to the same width).
EL = '\x1b[K' # clear to end of line
CR = '\r' # carriage return
sys.stdout.write(("%d hours %d minutes %s seconds" + EL + CR) % (h, m, s))
sys.stdout.flush()
A more decent approach (besides this shortcut by using literal sequences) is to use the official curses library.
import curses
curses.setupterm()
EL = curses.tigetstr('el')
CR = curses.tigetstr('cr')
And if CR really does not work on OSX as we want it to, then there might be goto in your termcaps to go to a specific position (e. g. first column) or you can use save_cursor (SC) and restore_cursor (RC) to restore an earlier saved position:
sys.stdout.write(SC + "%d hours %d minutes %s seconds" + EL + RC % (h, m, s))
Try this:
print h, "hours", m, 'minutes', s, 'seconds', '\r'
and you should also look at Alfe's answer :-)
In Python 3 you could use this kind of code:
print("{} hours, {} minutes, {} seconds".format(h, m, s), end = "\r")

How can I read one line from a telnet response with Python?

I was surprised that I couldn't find this question on here.
I would like to take extract one line from a telnet response and make it a variable. (actually one number from that line). I can extract up to where I need using telnet.read_until(), but the whole beginning is still there. The printout shows different statuses of a machine.
The line I am trying to get is formatted like this:
CPU Utilization : 5 %
I really only need the number, but there are many ':' and '%' characters in the rest of the output. Can anyone help me extract this value? Thanks in advance!
Here is my code (this reads the whole output and prints):
import telnetlib, time
print ("Starting Client...")
host = input("Enter IP Address: ")
timeout = 120
print ("Connecting...")
try:
session = telnetlib.Telnet(host, 23, timeout)
except socket.timeout:
print ("socket timeout")
else:
print("Sending Commands...")
session.write("command".encode('ascii') + b"\r")
print("Reading...")
output = session.read_until(b"/r/n/r/n#>", timeout )
session.close()
print(output)
print("Done")
Edit: some example of what an output could be:
Boot Version : 1.1.3 (release_82001975_C)
Post Version : 1.1.3 (release_82001753_E)
Product VPD Version : release_82001754_C
Product ID : 0x0076
Hardware Strapping : 0x004C
CPU Utilization : 5 %
Uptime : 185 days, 20 hours, 31 minutes, 29 seconds
Current Date/Time : Fri Apr 26 17:50:30 2013
As you say in the question:
I can extract up to where I need using telnet.read_until(), but the whole beginning is still there.
So you can get all of the lines up to and including the one you want into a variable output. The only thing you're missing is how to get just the last line in that output string, right?
That's easy: just split output into lines and take the last one:
output.splitlines()[:-1]
Or just split off the last line:
output.rpartition('\n')[-1]
This doesn't change output, it's just an expression that computes a new value (the last line in output). So, just doing this, followed by print(output), won't do anything visibly useful.
Let's take a simpler example:
a = 3
a + 1
print(a)
That's obviously going to print 3. If you want to print 4, you need something like this:
a = 3
b = a + 1
print(b)
So, going back to the real example, what you want is probably something like this:
line = output.rpartition('\n')[-1]
print(line)
And now you'll see this:
CPU Utilization : 5 %
Of course, you still need something like Johnny's code to extract the number from the rest of the line:
numbers = [int(s) for s in line.split() if s.isdigit()]
print(numbers)
Now you'll get this:
['5']
Notice that gives you a list of one string. If you want just the one string, you still have another step:
number = numbers[0]
print(number)
Which gives you:
5
And finally, number is still the string '5', not the integer 5. If you want that, replace that last bit with:
number = int(numbers[0])
print(number)
This will still print out 5, but now you have a variable you can actually use as a number:
print(number / 100.0) # convert percent to decimal
I'm depending on the fact that telnet defines end-of-line as \r\n, and any not-quite-telnet-compatible server that gets it wrong is almost certainly going to use either Windows-style (also \r\n) or Unix-style (just \n) line endings. So, splitting on \n will always get the last line, even for screwy servers. If you don't need to worry about that extra robustness, you can split on \r\n instead of \n.
There are other ways you could solve this. I would probably either use something like session.expect([r'CPU Utilization\s*: (\d+)\s*%']), or wrap the session as an iterator of lines (like a file) and then just do write the standard itertools solution. But this seems to be simplest given what you already have.
As I understand the problem, you want to select 1 line out of a block of lines, but not necessarily the last line.
The line you're interested in always starts with "CPU Utilization"
This should work:
for line in output.splitlines():
if 'CPU Utilization' in line:
cpu_utilization = line.split()[-2]
If you want to get only numbers:
>>> output = "CPU Utilization : 5 %"
>>> [int(s) for s in output.split() if s.isdigit()]
[5]
>>> output = "CPU Utilization : 5 % % 4.44 : 1 : 2"
>>> [int(s) for s in output.split() if s.isdigit()]
[5, 4.44, 1, 2]
EDIT:
for line in output:
print line # this will print every single line in a loop, so you can make:
print [int(s) for s in line.split() if s.isdigit()]
In [27]: mystring= "% 5 %;%,;;;;;%"
In [28]: ''.join(c for c in mystring if c.isdigit())
Out[28]: '5'
faster way :
def find_digit(mystring):
return filter(str.isdigit, mystring)
find_digit(mystring)
5

How can I print multiple things on the same line, one at a time?

I want to run a script, which basically shows an output like this:
Installing XXX... [DONE]
Currently, I print Installing XXX... first and then I print [DONE].
How can I instead print Installing xxx... and [DONE] on the same line?
For the specific problem of writing a new message on the same line, replacing what was there before, please see How to overwrite the previous print to stdout?. Most answers here interpreted the question as being about writing new text at the end of the current line.
For the problem of using a single print to output multiple things at once, see How can I print multiple things (fixed text and/or variable values) on the same line, all at once?.
Python 3 Solution
The print() function accepts an end parameter which defaults to \n (new line). Setting it to an empty string prevents it from issuing a new line at the end of the line.
def install_xxx():
print("Installing XXX... ", end="", flush=True)
install_xxx()
print("[DONE]")
Python 2 Solution
Putting a comma on the end of the print() line prevents print() from issuing a new line (you should note that there will be an extra space at the end of the output).
def install_xxx():
print "Installing XXX... ",
install_xxx()
print "[DONE]"
You can simply use this:
print 'something',
...
print ' else',
and the output will be
something else
no need to overkill by import sys. Pay attention to comma symbol at the end.
Python 3+
print("some string", end=""); to remove the newline insert at the end. Read more by help(print);
You should use backspace '\r' or ('\x08') char to go back on previous position in console output
Python 2+:
import time
import sys
def backspace(n):
sys.stdout.write((b'\x08' * n).decode()) # use \x08 char to go back
for i in range(101): # for 0 to 100
s = str(i) + '%' # string for output
sys.stdout.write(s) # just print
sys.stdout.flush() # needed for flush when using \x08
backspace(len(s)) # back n chars
time.sleep(0.2) # sleep for 200ms
Python 3:
import time
def backline():
print('\r', end='') # use '\r' to go back
for i in range(101): # for 0 to 100
s = str(i) + '%' # string for output
print(s, end='') # just print and flush
backline() # back to the beginning of line
time.sleep(0.2) # sleep for 200ms
This code will count from 0% to 100% on one line. Final value will be:
> python test.py
100%
Additional info about flush in this case here: Why do python print statements that contain 'end=' arguments behave differently in while-loops?
Use sys.stdout.write('Installing XXX... ') and sys.stdout.write('Done'). In this way, you have to add the new line by hand with "\n" if you want to recreate the print functionality. I think that it might be unnecessary to use curses just for this.
Most simple:
Python 3
print('\r' + 'something to be override', end='')
It means it will back the cursor to beginning, than will print something and will end in the same line. If in a loop it will start printing in the same place it starts.
None of the answers worked for me since they all paused until a new line was encountered. I wrote a simple helper:
def print_no_newline(string):
import sys
sys.stdout.write(string)
sys.stdout.flush()
To test it:
import time
print_no_newline('hello ')
# Simulate a long task
time.sleep(2)
print('world')
"hello " will first print out and flush to the screen before the sleep. After that you can use standard print.
sys.stdout.write will print without return carriage
import sys
sys.stdout.write("installing xxx")
sys.stdout.write(".")
http://en.wikibooks.org/wiki/Python_Programming/Input_and_output#printing_without_commas_or_newlines
Python appends newline as an end to print. Use end=' ' for python3 for print method to append a space instead of a newline. for python2 use comma at end of print statement.
print('Foo', end=' ')
print('Bar')
This simple example will print 1-10 on the same line.
for i in range(1,11):
print (i, end=" ")
Print has an optional end argument, it is what printed in the end.
The default is a newline, but you can change it to empty string. e.g. print("hello world!", end="")
If you want to overwrite the previous line (rather than continually adding to it), you can combine \r with print(), at the end of the print statement. For example,
from time import sleep
for i in xrange(0, 10):
print("\r{0}".format(i)),
sleep(.5)
print("...DONE!")
will count 0 to 9, replacing the old number in the console. The "...DONE!" will print on the same line as the last counter, 9.
In your case for the OP, this would allow the console to display percent complete of the install as a "progress bar", where you can define a begin and end character position, and update the markers in between.
print("Installing |XXXXXX | 30%"),
Here a 2.7-compatible version derived from the 3.0 version by #Vadim-Zin4uk:
Python 2
import time
for i in range(101): # for 0 to 100
s = str(i) + '%' # string for output
print '{0}\r'.format(s), # just print and flush
time.sleep(0.2)
For that matter, the 3.0 solution provided looks a little bloated. For example, the backspace method doesn't make use of the integer argument and could probably be done away with altogether.
Python 3
import time
for i in range(101): # for 0 to 100
s = str(i) + '%' # string for output
print('{0}\r'.format(s), end='') # just print and flush
time.sleep(0.2) # sleep for 200ms
Both have been tested and work.
This is a very old thread, but here's a very thorough answer and sample code.
\r is the string representation of Carriage Return from the ASCII character set. It's the same as octal 015 [chr(0o15)] or hexidecimal 0d [chr(0x0d)] or decimal 13 [chr(13)]. See man ascii for a boring read. It (\r) is a pretty portable representation and is easy enough for people to read. It very simply means to move the carriage on the typewriter all the way back to the start without advancing the paper. It's the CR part of CRLF which means Carriage Return and Line Feed.
print() is a function in Python 3. In Python 2 (any version that you'd be interested in using), print can be forced into a function by importing its definition from the __future__ module. The benefit of the print function is that you can specify what to print at the end, overriding the default behavior of \n to print a newline at the end of every print() call.
sys.stdout.flush tells Python to flush the output of standard output, which is where you send output with print() unless you specify otherwise. You can also get the same behavior by running with python -u or setting environment variable PYTHONUNBUFFERED=1, thereby skipping the import sys and sys.stdout.flush() calls. The amount you gain by doing that is almost exactly zero and isn't very easy to debug if you conveniently forget that you have to do that step before your application behaves properly.
And a sample. Note that this runs perfectly in Python 2 or 3.
from __future__ import print_function
import sys
import time
ANS = 42
FACTORS = {n for n in range(1, ANS + 1) if ANS % n == 0}
for i in range(1, ANS + 1):
if i in FACTORS:
print('\r{0:d}'.format(i), end='')
sys.stdout.flush()
time.sleep(ANS / 100.0)
else:
print()
This solution in Python 3.X specific:
When I need to do this, I'll generally just use
end=' '
For example:
# end='' ends the output with a <space>
print("Welcome to" , end = ' ')
print("stackoverflow", end = ' ')
This outputs as:
Welcome to stackoverflow
The space in end= can be replaced with any character. For example,
print("Welcome to" , end = '...')
print("stackoverflow", end = '!')
Which outputs as:
Welcome to...stackoverflow!
print() has a built in parameter "end" that is by default set to "\n"
Calling print("This is America") is actually calling print("This is America", end = "\n").
An easy way to do is to call print("This is America", end ="")
Just in case you have pre-stored the values in an array, you can call them in the following format:
for i in range(0,n):
print arr[i],
Found this Quora post, with this example which worked for me (python 3),
which was closer to what I needed it for (i.e. erasing the whole previous line).
The example they provide:
def clock():
while True:
print(datetime.now().strftime("%H:%M:%S"), end="\r")
For printing the on the same line, as others have suggested, just use end=""
I found this solution, and it's working on Python 2.7
# Working on Python 2.7 Linux
import time
import sys
def backspace(n):
print('\r', end='') # use '\r' to go back
for i in range(101): # for 0 to 100
s = str(i) + '%' # string for output
sys.stdout.write(string)
backspace(len(s)) # back for n chars
sys.stdout.flush()
time.sleep(0.2) # sleep for 200ms

Print to the same line and not a new line? [duplicate]

This question already has answers here:
How to overwrite the previous print to stdout?
(18 answers)
Why doesn't print output show up immediately in the terminal when there is no newline at the end?
(1 answer)
Closed last month.
Basically I want to do the opposite of what this guy did... hehe.
Python Script: Print new line each time to shell rather than update existing line
I have a program that is telling me how far along it is.
for i in some_list:
#do a bunch of stuff.
print i/len(some_list)*100," percent complete"
So if len(some_list) was 50, I'd get that last line printed 50 times over. I want to print one line and keep updating that line. I know I know this is probably the lamest question you'll read all day. I just can't figure out the four words I need to put into google to get the answer.
Update! I tried mvds' suggestion which SEEMED right. The new code
print percent_complete," \r",
Percent complete is just a string (I was abstracting the first time now I an trying to be literal). The result now is that it runs the program, doesn't print ANYTHING until after the program is over, and then prints "100 percent complete" on one and only one line.
Without the carriage return (but with the comma, half of mvds' suggestion) it prints nothing until the end. And then prints:
0 percent complete 2 percent complete 3 percent complete 4 percent complete
And so on. So now the new issue is that with the comma it doesn't print until the program is finished.
With the carriage return and no comma it behaves the exact same as with neither.
It's called the carriage return, or \r
Use
print i/len(some_list)*100," percent complete \r",
The comma prevents print from adding a newline. (and the spaces will keep the line clear from prior output)
Also, don't forget to terminate with a print "" to get at least a finalizing newline!
From python 3.x you can do:
print('bla bla', end='')
(which can also be used in Python 2.6 or 2.7 by putting from __future__ import print_function at the top of your script/module)
Python console progressbar example:
import time
# status generator
def range_with_status(total):
""" iterate from 0 to total and show progress in console """
n=0
while n<total:
done = '#'*(n+1)
todo = '-'*(total-n-1)
s = '<{0}>'.format(done+todo)
if not todo:
s+='\n'
if n>0:
s = '\r'+s
print(s, end='')
yield n
n+=1
# example for use of status generator
for i in range_with_status(10):
time.sleep(0.1)
For me, what worked was a combo of Remi's and siriusd's answers:
from __future__ import print_function
import sys
print(str, end='\r')
sys.stdout.flush()
In Python 3.3+ you don’t need sys.stdout.flush(). print(string, end='', flush=True) works.
So
print('foo', end='')
print('\rbar', end='', flush=True)
will overwrite ‘foo’ with ‘bar’.
for Console you'll probably need
sys.stdout.flush()
to force update. I think using , in print will block stdout from flushing and somehow it won't update
Late to the game - but since the none of the answers worked for me (I didn't try them all) and I've come upon this answer more than once in my search ... In python 3, this solution is pretty elegant and I believe does exactly what the author is looking for, it updates a single statement on the same line. Note, you may have to do something special if the line shrinks instead of grows (like perhaps make the string a fixed length with padded spaces at the end)
if __name__ == '__main__':
for i in range(100):
print("", end=f"\rPercentComplete: {i} %")
time.sleep(0.2)
As of end of 2020 and Python 3.8.5 on linux console for me only this works:
print('some string', end='\r')
Credit goes to: This post
If you are using Spyder, the lines just print continuously with all the previous solutions. A way to avoid that is using:
for i in range(1000):
print('\r' + str(round(i/len(df)*100,1)) + '% complete', end='')
sys.stdout.flush()
This works for me, hacked it once to see if it is possible, but never actually used in my program (GUI is so much nicer):
import time
f = '%4i %%'
len_to_clear = len(f)+1
clear = '\x08'* len_to_clear
print 'Progress in percent:'+' '*(len_to_clear),
for i in range(123):
print clear+f % (i*100//123),
time.sleep(0.4)
raw_input('\nDone')
As of 2021, for Python 3.9.0 the following solution worked for me in Windows 10, Pycharm.
print('\r some string ', end='', flush=True)
import time
import sys
def update_pct(w_str):
w_str = str(w_str)
sys.stdout.write("\b" * len(w_str))
sys.stdout.write(" " * len(w_str))
sys.stdout.write("\b" * len(w_str))
sys.stdout.write(w_str)
sys.stdout.flush()
for pct in range(0, 101):
update_pct("{n}%".format(n=str(pct)))
time.sleep(0.1)
\b will move the location of the cursor back one space
So we move it back all the way to the beginning of the line
We then write spaces to clear the current line - as we write spaces the cursor moves forward/right by one
So then we have to move the cursor back at the beginning of the line before we write our new data
Tested on Windows cmd using Python 2.7
Try it like this:
for i in some_list:
#do a bunch of stuff.
print i/len(some_list)*100," percent complete",
(With a comma at the end.)
For Python 3+
for i in range(5):
print(str(i) + '\r', sep='', end ='', file = sys.stdout , flush = False)
In those cases, with python 3.x, I'm using the following code:
for ii in range(100):
print(f"\rPercent: {ii+1} %", end=" "*20)
The problem with some other answers is that if your printed string goes shorter at one step, the last characters from the previous string won't be overwrited.
So I use end=" "*20 in order to overwrite the previous line with whitespace. Just make sure that 20 is longer than the length of your longest string.
Based on Remi answer for Python 2.7+ use this:
from __future__ import print_function
import time
# status generator
def range_with_status(total):
""" iterate from 0 to total and show progress in console """
import sys
n = 0
while n < total:
done = '#' * (n + 1)
todo = '-' * (total - n - 1)
s = '<{0}>'.format(done + todo)
if not todo:
s += '\n'
if n > 0:
s = '\r' + s
print(s, end='\r')
sys.stdout.flush()
yield n
n += 1
# example for use of status generator
for i in range_with_status(50):
time.sleep(0.2)
For Python 3.6+ and for any list rather than just ints, as well as using the entire width of your console window and not crossing over to a new line, you could use the following:
note: please be informed, that the function get_console_with() will work only on Linux based systems, and as such you have to rewrite it to work on Windows.
import os
import time
def get_console_width():
"""Returns the width of console.
NOTE: The below implementation works only on Linux-based operating systems.
If you wish to use it on another OS, please make sure to modify it appropriately.
"""
return int(os.popen('stty size', 'r').read().split()[1])
def range_with_progress(list_of_elements):
"""Iterate through list with a progress bar shown in console."""
# Get the total number of elements of the given list.
total = len(list_of_elements)
# Get the width of currently used console. Subtract 2 from the value for the
# edge characters "[" and "]"
max_width = get_console_width() - 2
# Start iterating over the list.
for index, element in enumerate(list_of_elements):
# Compute how many characters should be printed as "done". It is simply
# a percentage of work done multiplied by the width of the console. That
# is: if we're on element 50 out of 100, that means we're 50% done, or
# 0.5, and we should mark half of the entire console as "done".
done = int(index / total * max_width)
# Whatever is left, should be printed as "unfinished"
remaining = max_width - done
# Print to the console.
print(f'[{done * "#"}{remaining * "."}]', end='\r')
# yield the element to work with it
yield element
# Finally, print the full line. If you wish, you can also print whitespace
# so that the progress bar disappears once you are done. In that case do not
# forget to add the "end" parameter to print function.
print(f'[{max_width * "#"}]')
if __name__ == '__main__':
list_of_elements = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
for e in range_with_progress(list_of_elements):
time.sleep(0.2)
If you are using Python 3
then this is for you and it really works.
print(value , sep='',end ='', file = sys.stdout , flush = False)
Just figured this out on my own for showing a countdown but it would also work for a percentage.
import time
#Number of seconds to wait
i=15
#Until seconds has reached zero
while i > -1:
#Ensure string overwrites the previous line by adding spaces at end
print("\r{} seconds left. ".format(i),end='')
time.sleep(1)
i-=1
print("") #Adds newline after it's done
As long as whatever comes after '/r' is the same length or longer (including spaces) than the previous string, it will overwrite it on the same line. Just make sure you include the end='' otherwise it will print to a newline. Hope that helps!
for object "pega" that provides StartRunning(), StopRunning(),
boolean getIsRunning() and integer getProgress100() returning
value in range of 0 to 100, this provides text progress bar
while running...
now = time.time()
timeout = now + 30.0
last_progress = -1
pega.StartRunning()
while now < timeout and pega.getIsRunning():
time.sleep(0.5)
now = time.time()
progress = pega.getTubProgress100()
if progress != last_progress:
print('\r'+'='*progress+'-'*(100-progress)+' ' + str(progress) + "% ", end='', flush=True)
last_progress = progress
pega.StopRunning()
progress = pega.getTubProgress100()
print('\r'+'='*progress+'-'*(100-progress)+' ' + str(progress) + "% ", flush=True)

How to append two strings in Python?

I have done this operation millions of times, just using the + operator! I have no idea why it is not working this time, it is overwriting the first part of the string with the new one! I have a list of strings and just want to concatenate them in one single string! If I run the program from Eclipse it works, from the command-line it doesn't!
The list is:
["UNH+1+XYZ:08:2:1A+%CONVID%'&\r", "ORG+1A+77499505:ABC+++A+FR:EUR++123+1A'&\r", "DUM'&\r"]
I want to discard the first and the last elements, the code is:
ediMsg = ""
count = 1
print "extract_the_info, lineList ",lineList
print "extract_the_info, len(lineList) ",len(lineList)
while (count < (len(lineList)-1)):
temp = ""
# ediMsg = ediMsg+str(lineList[count])
# print "Count "+str(count)+" ediMsg ",ediMsg
print "line value : ",lineList[count]
temp = lineList[count]
ediMsg += " "+temp
print "ediMsg : ",ediMsg
count += 1
print "count ",count
Look at the output:
extract_the_info, lineList ["UNH+1+XYZ:08:2:1A+%CONVID%'&\r", "ORG+1A+77499505:ABC+++A+FR:EUR++123+1A'&\r", "DUM'&\r"]
extract_the_info, len(lineList) 8
line value : ORG+1A+77499505:ABC+++A+FR:EUR++123+1A'&
ediMsg : ORG+1A+77499505:ABC+++A+FR:EUR++123+1A'&
count 2
line value : DUM'&
DUM'& : ORG+1A+77499505:ABC+++A+FR:EUR++123+1A'&
count 3
Why is it doing so!?
While the two answers are correct (use " ".join()), your problem (besides very ugly python code) is this:
Your strings end in "\r", which is a carriage return. Everything is fine, but when you print to the console, "\r" will make printing continue from the start of the same line, hence overwrite what was written on that line so far.
You should use the following and forget about this nightmare:
''.join(list_of_strings)
The problem is not with the concatenation of the strings (although that could use some cleaning up), but in your printing. The \r in your string has a special meaning and will overwrite previously printed strings.
Use repr(), as such:
...
print "line value : ", repr(lineList[count])
temp = lineList[count]
ediMsg += " "+temp
print "ediMsg : ", repr(ediMsg)
...
to print out your result, that will make sure any special characters doesn't mess up the output.
'\r' is the carriage return character. When you're printing out a string, a '\r' will cause the next characters to go at the start of the line.
Change this:
print "ediMsg : ",ediMsg
to:
print "ediMsg : ",repr(ediMsg)
and you will see the embedded \r values.
And while your code works, please change it to the one-liner:
ediMsg = ' '.join(lineList[1:-1])
Your problem is printing, and it is not string manipulation. Try using '\n' as last char instead of '\r' in each string in:
lineList = [
"UNH+1+TCCARQ:08:2:1A+%CONVID%'&\r",
"ORG+1A+77499505:PARAF0103+++A+FR:EUR++11730788+1A'&\r",
"DUM'&\r",
"FPT+CC::::::::N'&\r",
"CCD+CA:5132839000000027:0450'&\r",
"CPY+++AF'&\r",
"MON+712:1.00:EUR'&\r",
"UNT+8+1'\r"
]
I just gave it a quick look. It seems your problem arises when you are printing the text. I haven't done such things for a long time, but probably you only get the last line when you print. If you check the actual variable, I'm sure you'll find that the value is correct.
By last line, I'm talking about the \r you got in the text strings.

Categories

Resources