Today, I'm learning the built-in function chr. And through ascii-table search, I found \x08 means backspace. So I played a bit with it. But the result confused me:
In [52]: print '1\x08'
1
In [53]: print '1\x082'
2
It seems that only follow by another character, \x08 will behave like a backspace, why does this happened? How \x08 behaves in a string?
It's behaving like a backspace in both cases, which is to say it moves your cursor back one space. It does not, however, delete what's there unless you write something else. So in the first case, the 1 remains, but in the second it is overwritten with a 2.
Backspace only moves the cursor by one character, it does not actually delete it. This for example results in 193:
print('123\x08\x089')
You can use space to actually "delete" the character...
1---- backspace simply move the cursor to the left one space, and
if you use the work or other editor it will also delete the left one character.
and what you must know is that backspace is also a character the same as 1 or a.
2---- the terminal as our default output device, you can also put him as a file.
So if you use
print '1\x08'
it means that you write a 1 and a backspace in the file stdout.
if you read the file, the system reads 1 + breakspace, you will get an 1.
and if you use
print '1\x082'
it means that you write a 1, a backspace and a 2 in the file stdout.
if you read the file, the system get 1 + breakspace + 2, when you print them, you will only get an 2, because it covers the first 1 when you use backspace.
for detail you can see the next test code
if __name__ == "__main__":
print "1\x08"
print "1\x082"
f = open("1.txt", "w")
f.write("1\x08\x082")
f.close();
f = open("1.txt", "r")
str = f.readlines( )
print len(str), str
for s in str:
print "s=|" + s + "|"
you can see the string s=|1\x08\x082| display s=2|. becasue the |1 not display when backspace two times.
Related
Carriage return or \r works as you have shifted your cursor to the beginning of the string or line. so, whenever you will use this special escape character \r, the rest of the content after the \r will come at the front of your line and will keep replacing your characters one by one until it takes all the contents left after the \r in that string. right???
However, with me it only prints what is after \r
so,
print("don't wish for it work \r for it")
print only "for it"
Try:
print("don't wish for it work \n for it")
If you run the print statment from terminal, the output will be
for itish for it work
If you run the exact statement from IDE (Pycharm), the output will be for it. This could be due to a bug/feature. In order to get the exact output in Pycharm IDE, go to Run > Edit Configuration > Emulate Terminal in output console and select this option. You will get the exact result as described in your statement.
for itish for it work
Other answers seem to be providing little explanation for what's the problem.
When you are running your code, two cases can happen:
\r starts to overwrite character from previous line (without clearing the entire line) which will give you following output:
print("don't wish for it work \r for it")
|don't wish for it work -- line 1
+| for it -- line 2
| for itish for it work -- line 1 overwritten by line 2 (only overlapping chars)
\r clears the previous line and writes content following \r, which will give you following output:
print("don't wish for it work \r for it")
|don't wish for it work -- line 1
+| for it -- line 2
| for it -- line 1 cleared. line 2 is output
Since behaviour of carriage return can vary from system to system, consider using \n as shown in #KJDII's answer or understand and configure the behaviour for which system you will run it on.
I'm trying to print out a string with the end=\r to send the cursor back to beginning of the line, and overwrite the printed string using a for loop
This is the code thus far I got :
import time
print("░░░░░░░░░░░░░", end='\r')
for i in ("SECRET"):
print(i ,end='')
time.sleep(0.3)
Ideally, it should slowly overwrite some of the dotted pattern characters with characters from `"SECRET" every 0.3 seconds.
However, when run, the for loop instead iterates and prints characters on a single space, overwriting the characters it prints out itself, instead of advancing to the next available space, overwriting the dot pattern there and typing out the remaining characters in the string it iterates over
Removing the entire print statement associated with the dotted pattern characters allows the loop to function normally, printing out the string it iterates over properly, however, it is needed for the loop to print out the string and overwrite the dotted characters
Essentially, I want to overwrite some of the dotted pattern characters one by one using characters from the string the for loop iterates over, with the help of \r
I am on Ubuntu Studio
Screen output is line-buffered. This means that when you print something followed by a newline it appears on the screen immediately, but if you print something without a newline it might take a while to appear.
This is what's happening to you -- the output inside the for loop is not followed by a newline, so it doesn't appear onscreen immediately.
You can add flush=True to the print call to force the output to appear immediately instead of waiting:
print(i, end='', flush=True)
you can't overwrite characters in python.
you can, though, clear the whole screen by using os.system('cls') on windows or os.system('clear') on linux and unix.
here is the full code:
import time, os
output = '░░░░░░░░░░░░░'
for i in range(7):
print(output)
output = "SECRET"[:i]+output[i:]
time.sleep(0.3)
if os.name == 'nt': #on windows
os.system("cls")
else:
os.system("clear") #not on windows
print(output)
also, this will only work when you are not running from the shell and if you want to see the full output, write time.sleep(1) at the end.
So, I was studying basic things about Python. I encountered print function that basically prints something.
I learned that I could use [end=""] to end the print function.
For example,
my_job = 'hacker'
print(my_job, end="")
Basically gives me,
hacker
Another example, using the same values as above,
print(my_job, end="test")
Basically gives me,
hackertest
However, I then saw a cool thread in this site about how does the [end=""] function really works. I then noticed #Ritesh Karwa post this code,
myjob = 'hacker'
for c in myjob: print(c, end=" ")
Basically gave him,
h a c k e r
I know that the space inside the "" in the [end=] allowed the output to have spaces, but just how did that work? I mean, removing the [for c in myjob:] and only using the print function, the output became,
hacker
What is the mechanism behind this [for c in myjob:] that allowed the [end=] to apply spaces in between of the letters, resulting into this output,
h a c k e r
I wanted to ask #Ritesh Karwa directly through comments, but I don't have enough reputation. I'm not confident that I asked my question clearly, but I did my best. Thank you in advance for the helpful answers. I'm also using Python 3.xx
In Python, strings are also iterators (i.e. you can create a loop that will access them character by character). In this case:
for c in myjob:
is creating a loop where c will in turn have the value of each individual character in myjob.
If you then just did print(c) in the loop you would end up with
h
a
c
k
e
r
What the end=' ' is doing is replacing the default \n (newline) character that would normally force each print statement to print on a separate line as above and instead printing the contents of end=' ' (i.e. a space) after each print. That's giving you
h a c k e r
One thing you often have to remember after using end= is that the next print (which may be completely unrelated) will resume directly after the previous print, so would appear on the same line. People often would use a separate print() to print a newline so the next, unrelated print statement starts on a new line.
myjob is a string object, therefore an iterable. That means, that you can for example apply for loops such as for letter in myjob to iterate over all letters in the string.
As you have seen the optional end parameter of print replaces the standard end, which is a new line character with the one specified. So in this case, each occurrence in your for loop, the next letter is printed followed by a space. If you don't specify an end you will see that each letter would be printed to a new line.
end=“” removes the invisible new line (\n) that gets added at the end of a printing action.
Useful for for loops if you don’t want to get your results on separate lines.
I'm working on writing a simple Hangman game in Python from what I know so far (I'm doing Learn Python the Hard Way) and so far I have this:
from sys import argv
import random
script_name, dict_file = argv
hang_list = open(dict_file).read().splitlines()
hang_list = filter(None, hang_list)
word = random.choice(hang_list)
guesses = ''
def compare_words():
global guesses
new_word = ''
for char in word:
if char in guesses:
new_word += char
else:
new_word += "_"
return new_word
def test_letter():
global guesses
letter = raw_input("Guess a letter: ")
guesses += letter
new_word = compare_words()
print "\nCurrent guesses: %s" % guesses
print "%s\n\n" % new_word
if new_word == word:
print "You won!"
else:
test_letter()
test_letter()
I've yet to implement the scoring system (piece of cake) but I have an issue with the layout. As you can tell, this will print "Current guesses: " and the new word each time; however, what I want is four lines that look like:
Guess a letter:
Guesses: abczy
__c__b_
And have those three lines keep updating. However, I am having trouble figuring out how to make the print replace stdout. I believe I need to use the \r escape character, yet I've tried placing that in various places but can't get it to work. So, how should I modify this to get it to replace? I would prefer not to just clear, as then it still makes things a bit messy; I want to just replace what's there. Thanks!
It would be a bit tricky to make this work for all terminals, but if yours understands ANSI escape codes like mine does, this might work:
...
if new_word == word:
print "You won!"
else:
print '\033[F'*7
print ' '*17 + '\b'*17 + '\033[F'
test_letter()
This relies on the ANSI code F: move the cursor up one line; backspaces (\b) alone have no effect once the beginning of the line is reached.
The first print takes you back up to the input line and the second deletes the character that was previously entered.
You can use the escape characters \033c and this will erase the code in a terminal window and put the cursor at the top left.
For example this code:
import time
print("text 1")
time.sleep(1)
print('\033c')
time.sleep(1)
print("text 2")
This code will print "text 1" wait one second, clear the console, wait one second and then print "text 2".
So you could use the code
def test_letter():
print("\033c")
global guesses
letter = raw_input("Guess a letter: ")
guesses += letter
new_word = compare_words()
print "\nCurrent guesses: %s" % guesses
print "%s\n\n" % new_word
if new_word == word:
print "You won!"
else:
test_letter()
What this code will do is clear the console, ask the person to guess a number, display that four line piece of code that you wanted and then clear the console again.
I hope this helps!
If you want to replace the content of a specific line, from a specific position, you can use ANSI Escape Codes. To do this, make sure that you're using stdout.write() rather than print(). You can access this method by using the following import statement:
from sys import stdout
Then, in order to navigate the "cursor" (where text printed with this method will go), use the escape code \u001b[<L>;<C>H (or \u001b[<L>;<C>F where <L> and <C> represent the respective line number and character index of the desired position. For example, if you wanted to set the cursor to line 3; character 2, you would do the following.
stdout.write(u"\u001b[3;2H")
Note the u proceeding the double-quoted string. This is required in Python 2.x, since it contains special characters, but can be omitted in Python 3 and above.
Once you have set the cursor to be at the desired position, anything you write will replace the characters that currently reside there. This is important, because if the replacement string is shorter than the original, you may end up with trailing legacy characters. The simplest way to deal with this is to pad the printing string in spaces.
After doing this you should probably move the cursor back to the end of stdout, using the same method, and flush the output with stdout.flush().
Example
Let's say I had the following output on the terminal:
Name: Shakespeare
Score: 0
Some text...
I could change the score to 1 by running the following:
stdout.write(u"\u001b[2;8H")
stdout.write("1")
stdout.write(u"\u001b[5;0H")
stdout.flush()
Again, the u is optional in Python 3 and up.
Notes
This line-and-character-number method applies to all output currently being displayed in the terminal. This means that if you have anything left from another program or command, for example
$ python game.py
so it is best to clear the output at the start of your program, with something like print(u"\033c"), or os.system("clear"), otherwise you may end up writing to the wrong line.
Also, if your going to use stdout.write() anywhere else, remember to put \n at the end if you want to go to the next line.
The \r character is a carriage return, which means it will return the cursor to the start of the current line. That's OK if you want to redraw the line the cursor is on, but no good if you want to redraw other lines.
To do what you want, you need to use a terminal library like curses on Linux or the console API on Windows. If you are just working on Linux and want a simpler way to access colours, cursor movement and input without echo, you could do worse than try out blessed (https://pypi.python.org/pypi/blessed/).
If you need a cross platform API to do this sort of thing, there is no pure Python way to handle it all yet, but I am working on one. The Screen class in https://github.com/peterbrittain/asciimatics cover all the features above in a cross-platform manner.
How do i get rid of the extra character at the end of a line when i flush output?
Output:
{Fifth Level} Last Key Ran: 7 Output: -7 =
That '=' is what i want to get rid of.
code:
for number in str(fourth_level):
x=int(number)
x=x^(priv_key-pub_key)
print "\r{Fifth Level} Last Key Ran:",str(number),"Output:",x,
sys.stdout.flush()
time.sleep(sleep_time)
fifth_level.append(x)
Also is there any way to get multiple lines outputting data at the same time without going down one line or changing format? Using flush it gets rid of the second line output.
As a side note, check the ,x, part of the print statement. That 'x' is fishy.
For string manipulations, try writing everything into a temporary string first. You can then edit that string. This will give you more control over editing it.
Also, rstrip might do the trick if the characters being displayed are consistent.
Reference:
* http://docs.python.org/library/string.html
"string.rstrip(s[, chars]) Return a copy of the string with trailing characters removed."