Python 3 print over same line in loop - python-3.x

I am trying to print over 1 line continuously. In 2.7 I could use print '\r<stuff here>', and that would overwrite the previous line each time. In 3.5+, I've read suggestions like the following: print('\r<stuff here>', end=' ') but this is leaving "dangling" characters when a previous step in the loop is longer.
For example:
for foo in ['55555', '333', '1']:
print('\r', foo, end=' ')
results in
1 3 5
since each line is longer than the next by the ending space.
Suggestions?

Just compute the number of spaces needed to overwrite the longest string and use it as end for print
values = ['55555', '333', '1']
end_spaces = ' '*max(len(x) for x in values)
for foo in values:
print('\r', foo, end=end_spaces)

Related

How to skip N central lines when reading file?

I have an input file.txt like this:
3
2
A
4
7
B
1
9
5
2
0
I'm trying to read the file and
when A is found, print the line that is 2 lines below
when B is found, print the line that is 4 lines below
My current code and current output are like below:
with open('file.txt') as f:
for line in f:
if 'A' in line: ### Skip 2 lines!
f.readline() ### Skipping one line
line = f.readline() ### Locate on the line I want
print(line)
if 'B' in line: ## Skip 4 lines
f.readline() ### Skipping one line
f.readline() ### Skipping two lines
f.readline() ### Skipping three lines
line = f.readline() ### Locate on the line I want
print(line)
'4\n'
7
'1\n'
'9\n'
'5\n'
2
>>>
Is printing the values I want, but is printing also 4\n,1\n... and besides that, I need to write several f.realines()which is not practical.
Is there a better way to do this?
My expected output is like this:
7
2
Here is a much simpler code for you:
lines=open("file.txt","r").read().splitlines()
#print(str(lines))
for i in range(len(lines)):
if 'A' in lines[i]:
print(lines[I+2]) # show 2 lines down
elif 'B' in lines[i]:
print(lines[I+4]) # show 4 lines down
This reads the entire file as an array in which each element is one line of the file. Then it just goes through the array and directly changes the index by 2 (for A) and 4 (for B) whenever it finds the line it is looking for.
if you don't like repeated readline then wrap it in a function so the rest of the code is very clean:
def skip_ahead(it, elems):
assert elems >= 1, "can only skip positive integer number of elements"
for i in range(elems):
value = next(it)
return value
with open('file.txt') as f:
for line in f:
if 'A' in line:
line = skip_ahead(f, 2)
print(line)
if 'B' in line:
line = skip_ahead(f, 4)
print(line)
As for the extra output, when the code you have provided is run in a standard python interpreter only the print statements cause output, so there is no extra lines like '1\n', this is a feature of some contexts like the IPython shell when an expression is found in a statement context, in this case f.readline() is alone on it's own line so it is detected as possibly having a value that might be interesting. to suppress this you can frequently just do _ = <expr> to suppress output.

Is it possible to insert all but the last separator when printing from a Python 3 for loop?

Please see the below example for the sake of a clear question:
This syntax:
print('a','b','c',sep=' # ')
yields this output:
a # b # c
This is the output that I want to yield, but from within a for loop.
The attempts that I have made so far are:
for item in ['a','b','c']:
print(item,sep=' # ')
but this yields:
a
b
c
and:
for item in ['a','b','c']:
print(item,end=' # ')
but this yields:
a # b # c #
Is there a way to produce the output:
a # b # c
from this for loop specifically?
* Further clarification since it seems the details are important for the answer *
The full set up is as follows:
for fruit in df.index.year.unique():
total = df[df.index.year == year]['Number of Fruits'].sum()
print(fruit + ' Total: ' + str(total))
and I specifically want to print each fruit and total on the same line separated by a ' | ', but without the ' | ' separator appearing at the end.
Thanks!
If the reason you want to use a loop is because you want to print an arbitrary number of items with separators, then you can use print with unpacking.
lst = ['a', 'b', 'c']
print(*lst, sep=' # ') # 'a # b # c'
Since a single IO call is faster than using print in a for-loop, there is no real reason not to use it.
As for the specific use case you provided, here is how you would adapt the above solution.
lst = []
for fruit in df.index.year.unique():
total = df[df.index.year == year]['Number of Fruits'].sum()
lst.append('{} Total: {}'.format(fruit, total))
print(*lst, sep=' # ')
You can try this one if you want your result with a for loop:-
t = ['a','b','c']
for i in t[:-1]:
print(i, end=' # ')
print(t[-1])
Also the sep didn't work because it separates two or more elements; and can't do that on one element.
You can let the loop print one more # at end, after that just remove that from screen like so:
for i in ['a','b','c']:
print(i, end=' # ')
print('\b\b ')
\b is used to move cursor one place before and then a there is a space in the print command, so that the last # will be overwritten with a space, and no longer will be visible
You can see that code in action over here:
lst1 = ['a','b','c']
for item in lst1:
print(item,end=' # \n')
Output:
 
a #
b #
c #  
Use end instead of seperator for the desired output. Hopefully, it's helpful!!

How to sleep in Python 3 and remain in the same line?

I want to print a message with end=''
Sleep for 1 second
Remain on the same line
Erase the previous message using '\b'
Print a new message
Back to step 1
Example:
First output:
1
Second output:
2
Third output:
3
Remains in the same line
NOT: 123
Are you set on using \b? You can use \r to move the cursor back to the beginning of the line, which will let you write over stuff that is already there. If there's a chance that later lines will be shorter than previous ones, you should pad the new lines with whitespace on the right. Something like:
def f(x):
for i in range(1, x+1):
print(end='\r', flush=True)
print('**{}**'.format(i), end='', flush=True)
time.sleep(1)
f(3)

Pulling a list of lines out of a string

Beginning
Line 2
Line 3
Line 4
Line 5
Line 6
End
Trying to pull off line 2 through line 6. Can't do it to save my soul.
a is the saved string I'm searching through.
b = re.findall(r'Beginning(.*?)End', a)
Doesn't give me a thing, just a blank b. I know it's because of the newlines but how do I go about detecting and moving on forward with the newlines. I've tried, not knowing exactly for sure how I'm suppose to use MULTILINE or DOTALL. Nothing changed.
How do I go about getting it to put lines 2 through 6 in b?
To add in this will occur multiple times through the same file that I need to perform this search and pull technique. I have no other easy way of doing this since the information in Lines 2-6 need to be looked through further to pull off data that will be put into a csv file. Since some of the data contains hours and some of the data doesn't contain hours, aka Unavailable, I need to be able to pull off and differentiate between the two occurrences.
string = """Beginning
Line 2
Line 3
Line 4
Line 5
Line 6
End
"""
lines = string.splitlines()
answer = []
flag = False
for line in lines:
line = line.strip()
if not line: continue
if line == "Beginning":
flag = True
continue
if line == "End": flag = False
if not flag: continue
answer.append(line)
Output:
In [209]: answer
Out[209]: ['Line 2', 'Line 3', 'Line 4', 'Line 5', 'Line 6']
You could make a function that takes a multi-line string, then a starting line, and an ending line.
def Function(string, starting_line, ending_line):
if "\n" in string: #Checks for whether or not string is mult-line
pass
else:
return "The string given isn't a multiline string!" #If string isn't multiline, then Function returns a string explaining that string isn't a multi-line string
if ending_line < starting_line: #Checks if ending_line < starting_line
return "ending_line is greater than starting_line!" #If ending_line < starting_line, then Function returns a string explaining that ending_line > starting_line
array = [] #Defines an array
for i in range(len(string)): #Loops through len(string)
if list(string)[i] = "\n": #Checks whether list(string)[i] = a new line
array.append(i) #Appends i to array
return string[array[starting_line - 1]::array[ending_line - 1]]
print(Function(a, 3, 7))
This code should return:
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6

remove the item in string

How do I remove the other stuff in the string and return a list that is made of other strings ? This is what I have written. Thanks in advance!!!
def get_poem_lines(poem):
r""" (str) -> list of str
Return the non-blank, non-empty lines of poem, with whitespace removed
from the beginning and end of each line.
>>> get_poem_lines('The first line leads off,\n\n\n'
... + 'With a gap before the next.\nThen the poem ends.\n')
['The first line leads off,', 'With a gap before the next.', 'Then the poem ends.']
"""
list=[]
for line in poem:
if line == '\n' and line == '+':
poem.remove(line)
s = poem.remove(line)
for a in s:
list.append(a)
return list
split and strip might be what you need:
s = 'The first line leads off,\n\n\n With a gap before the next.\nThen the poem ends.\n'
print([line.strip() for line in s.split("\n") if line])
['The first line leads off,', 'With a gap before the next.', 'Then the poem ends.']
Not sure where the + fits in as it is, if it is involved somehow either strip or str.replace it, also avoid using list as a variable name, it shadows the python list.
lastly strings have no remove method, you can .replace but since strings are immutable you will need to reassign the poem to the the return value of replace i.e poem = poem.replace("+","")
You can read all non-empty lines like this:
list_m = [line if line not in ["\n","\r\n"] for line in file];
Without looking at your input sample, I am assuming that you simply want your white spaces to be removed. In that case,
for x in range(0, len(list_m)):
list_m[x] = list_m[x].replace("[ ](?=\n)", "");

Resources