I have written a small tool that iterates over a wordlist and I want it to print each line from the wordlist over the previous line, I have tried the following but it has issues.
print(word + (100 * " "), end="\r", flush=True)
This works as expected in VSCodes in-built terminal but when I run the same tool in either the OS's (Xfce) in-built terminal or Terminator each "word" is printing on a newline
Does anyone know why this is happening all my research just points me on how to do it, which doesn't help as the way to do it is what has this issue.
Thanks
This is because depending on your window width (and word length), each string may be longer than the line. So the next print statement is 'overwriting' the previous string, but since that previous string jumped a line, so the new string starts on that new line.
You can see this in action by printing 99 spaces followed by a * or some other character:
print(word + (99 * " ") + "*")
Depending on your window width and word length, this may or may not jump a line, as demonstrated by where there "*" prints.
Related
I want it to produce the number next to a word so that I can ask the user to select the word by using the corresponding number.
This is my code
alt_words = hlst
loopnum = 8
for i in range(loopnum):
if i < len(alt_words):
print('{0}. {1:<20}'.format((i+1), alt_words[i]), end =' ')
if i == 0:
print('', end=' ')
if i + 9 <= len(alt_words):
print('{0}. {1:<20}'.format((i+9), alt_words[i+8]), end =' ')
if i + 17 <= len(alt_words):
print('{0}. {1:<20}'.format((i+17), alt_words[i+16]), end=' ')
print('\n'+'-'*80)
It produces this
The first number of each line gets printed on the left, but the word on the right, while the rest of the numbers and words get printed RTL. It seems that once python has started printing on a line LTR it can switch to RTL, but not back from RTL to LTR. Note how even the periods are printed to the right of the number for the second set of numbers on each line.
It works perfectly well and looks nice with english words:
I am guessing a work around might involve putting the number after the word, but I figure there must be a better way.
Put a Right-to-Left Embedding character, u'\u202B', at the beginning of each Hebrew word, and a Pop Directional Formatting character, u'\u202C', at the end of each word.
This will set the Hebrew words apart as RTL sections in an otherwise LTR document.
(Note that while this will produce the correct output, you're also dependent on the terminal application in which you're running this script having implemented the Unicode Bidirectional Algorithm correctly.)
See Bi-directional (BiDi) layout implementation in pure python.
Install with:
pip install python-bidi
Example usage:
from bidi.algorithm import get_display
print(get_display('LTR text with RTL text (טקסט לדוגמא) will be printed correctly'))
The following package is also available if you are using Django:
http://pypi.python.org/pypi/django-bidi-utils
So I am trying to use sys.stdout.write() to rewrite the current line it is on and replace it with different text. But I want this to happen for multiple lines of output.
# I am looking at having 2 lines with changing values in them that will keep over writing themselves without moving any further down.
import sys
for i in range(10):
sys.stdout.write("\r" + "Hello" + str(i) + "\n + "Hello" + str(i) * 2)
sys.stdout.flush()
I tried this but every time it hits the \n it will indefinately increase the numbers of lines without clearing everything.
stdout\stderr don't work like that. You can send control characters to your terminal to delete characters but once a line is sent it's basically fixed.
What you actually need is ncurses which gives you much more control over the display and cursor position when writing to a terminal.
I am trying to update the last line in PyCharm's console. Say, I print a and then I want to change it to c. However, I encounter the following problem. When I run:
print 'a\bc'
it prints
a c
while the desired output (which is also what I see in the Windows console) is:
c
Is there a way to move the cursor back in PyCharm's console? or maybe delete the whole line?
This is not a bug, this is a limitation of the interactive console found both in PyCharm, and in the IDLE shell.
When using the command prompt of windows, or a linux shell - the \b character is interpreted as a backspace and implemented as it is being parsed - However, in the interactive console of PyCharm and IDLE the \b character and many others are disabled, and instead you simply get the ASCII representation of the character (a white space in most cases).
It's a known bug: http://youtrack.jetbrains.com/issue/PY-11300
If you care about this, please get an account on the bug tracker and upload the bug to give it more attention.
The \r works. I know this is ASCII Carriage Return, but i use this as a workaround
print("\ra")
print("\rc")
will yield in c in the console
By the way, backspace is a ASCII Character
I just ran into the same issue in PyCharm (2019.1) and stumbled on this post. It turns out that you can use the \b character if you use the sys.stdout.write function instead of print. I wasn't able to get any of the above examples working within PyCharm using the print function.
Here's how I update the last line of text in my code assuming I don't need more than 100 characters:
# Initialize output line with spaces
sys.stdout.write(' ' * 100)
# Update line in a loop
for k in range(10)
# Generate new line of text
cur_line = 'foo %i' % k
# Remove last 100 characters, write new line and pad with spaces
sys.stdout.write('\b' * 100)
sys.stdout.write(cur_line + ' '*(100 - len(cur_line)))
# ... do other stuff in loop
This should generate "foo 1", then replaced with "foo 2", "foo 3", etc. all on the same line and overwriting the previous output for each string output. I'm using spaces to pad everything because different programs implement the backspace character differently, where sometimes it removes the character, and other times it only moves the cursor backwards and thus still requires new text to overwrite.
I've got to credit the Keras library for this solution, which correctly updates the console output (including PyCharm) during learning. I found that they were using the sys.stdout.write function in their progress bar update code.
I'm trying to write a function to display a custom view when users press the tab button. Apparently "set_completion_display_matches_hook" function is what I need, I can display a custom view, but the problem is that I have to press Enter to get a prompt again.
The solution in Python2 seems to be that (solution here):
def match_display_hook(self, substitution, matches, longest_match_length):
print ''
for match in matches:
print match
print self.prompt.rstrip(),
print readline.get_line_buffer(),
readline.redisplay()
But it doesn't work with Python3. I made these syntax changes :
def match_display_hook(self, substitution, matches, longest_match_length):
print('\n----------------------------------------------\n')
for match in matches:
print(match)
print(self.prompt.rstrip() + readline.get_line_buffer())
readline.redisplay()
Any ideas please ?
First, the Python 2 code uses commas to leave the line unfinished. In Python 3, it's done using end keyword:
print(self.prompt.rstrip(), readline.get_line_buffer(), sep='', end='')
Then, a flush is required to actually display the unfinished line (due to line buffering):
sys.stdout.flush()
The redisplay() call does not seem to be needed.
The final code:
def match_display_hook(self, substitution, matches, longest_match_length):
print()
for match in matches:
print(match)
print(self.prompt.rstrip(), readline.get_line_buffer(), sep='', end='')
sys.stdout.flush()
The redisplay() function
voidrl_redisplay (void)
Change what's displayed on the screen to reflect the current contents of rl_line_buffer.
In your example you have written to stdout, but not changed that buffer.
Print and flush as described by in other answer should work.
One issue you will have, however, is cursor position. Say you have this scenario:
$ cmd some_file
^
+---- User has back-tracked here and want to insert an option.
<TAB> completion with print and flush will put cursor
at end of `some_file' and the line will get an extra 15
spaces after that ...
To remedy this one way is to first get cursor position, then use ANSI sequences to re-position the cursor.
buf = readline.get_line_buffer()
x = readline.get_endidx()
print(self.prompt + buf, end = '')
if x < len(buf):
""" Set cursor at old column position """
print("\r\033[%dC" % (x + len(self.prompt)), end = '')
sys.stdout.flush()
Now, of course, you get another issue if prompt has ANSI sequences in-iteself. Typically color or the like. Then you can not use len(prompt) but have to find printed / visible length.
One has to use open and close bytes elsewhere, typically \0x01 and \0x02 respectively.
So one typically get:
prompt = '\001\033[31;1m\002VISIBLE_TEXT\001\033[0m\002 '
instead of:
prompt = '\033[31;1mVISIBLE_TEXT\033[0m '
With those guards it should be easy enough to strip out the visible text.
Typically something like:
clean_prompt = re.sub(r'\001[^\002]*\002', '', prompt))
Cache the length of that and use when printing the readline manually. Note that you also have to remove the guards when using it manually - as in the hook function. (But it is needed in input(prompt)
this one worked for me for redisplaying substitution and the end of matches display for python3:
def match_display_hook(self, substitution, matches, longest_match_length):
print("")
for match in matches:
print(match)
print("")
sys.stdout.write(substitution)
sys.stdout.flush()
return None
while previous ones using print prompt didn't. (didn't get to the bottom of the problem)
For practice, I'm trying to do some stuff in Python. I've decided to make a simple hangman game - I'm not making a GUI. The game would start with a simple input(). Now, I'd like next line to, beside asking for input, to delete the hidden word. I've tried using \b (backspace character), but it's not working. Something like:
word = input("Your word: ")
for i in range(len(word) + 12):
print("\b")
Now, printing the backlash character is supposed to delete the input and "Your word", but it isn't doing anything. If I do this in IDLE I get squares, and I get nothing if I open it by clicking.
How to accomplish this? I'm afraid I wasn't too clear with my question, but I hope you'll see what I meant. :)
\b does not erase the character before the cursor, it simply moves the cursor left one column. If you want text entry without echoing the characters then look at getpass.
I assume the player entering the word wants to be sure they've entered it correctly so you probably want to display the word as they're typing it right?
How about printing enough \ns to move it off the screen when they're done or issue a clear screen command?
You mentioned this was a simple game so a simple solution seems fitting.
[Edit] Here's a simple routine to clear the console on just about any platform (taken from here):
def clearscreen(numlines=100):
"""Clear the console.
numlines is an optional argument used only as a fall-back.
"""
import os
if os.name == "posix":
# Unix/Linux/MacOS/BSD/etc
os.system('clear')
elif os.name in ("nt", "dos", "ce"):
# DOS/Windows
os.system('CLS')
else:
# Fallback for other operating systems.
print '\n' * numlines
word = raw_input("Your word: ")
import sys
sys.stdout.write("\x1b[1A" + 25*" " + "\n")
This will replace the last line printed with 25 spaces.
I think part of your problem is that input is echoing the Enter that terminates your word entry. Your backspaces are on another line, and I don't think they'll back up to the previous line. I seem to recall a SO question about how to prevent that, but I can't find it just now.
Also, I believe print, by default, will output a newline on each call, so each backspace would be on its own line. You can change this by using an end='' argument.
Edit: I found the question I was thinking of, but it doesn't look like there's any help there. You can look at it if you like: Python input that ends without showing a newline