7

I want to print Text 'Loading...' But its dots would be moving back and forward (in shell).

I am creating a text game and for that it will look better.
I know writing slowly a word but dots also have to go back.

I am thinking that I should forget dots to come back.And for that:

import sys
import time
shell = sys.stdout.shell
shell.write('Loading',"stdout")
str = '........'
for letter in str:
    sys.stdout.write(letter)
    time.sleep(0.1)

What do you think?
If you have that dots would be moving back and forward Then please share with me.
If you want more information I am ready to Provide to you.
Thanks

2
  • shell is not a property of sys.stdout, so this can't work. Plus, the write method of a file descriptor takes just one argument. Moreover, you're overriding the 'str' builtin, and that's a bad practice. So, please edit your code providing at least a working example (even if it doesn't do what you expect). Commented Jun 17, 2017 at 16:33
  • the link will expire after 30 or 27 days. Commented Jun 19, 2017 at 20:26

6 Answers 6

7

You can use backtracking via backspace (\b) in your STDOUT to go back and 'erase' written characters before writing them again to simulate animated loading, e.g.:

import sys
import time

loading = True  # a simple var to keep the loading status
loading_speed = 4  # number of characters to print out per second
loading_string = "." * 6  # characters to print out one by one (6 dots in this example)
while loading:
    #  track both the current character and its index for easier backtracking later
    for index, char in enumerate(loading_string):
        # you can check your loading status here
        # if the loading is done set `loading` to false and break
        sys.stdout.write(char)  # write the next char to STDOUT
        sys.stdout.flush()  # flush the output
        time.sleep(1.0 / loading_speed)  # wait to match our speed
    index += 1  # lists are zero indexed, we need to increase by one for the accurate count
    # backtrack the written characters, overwrite them with space, backtrack again:
    sys.stdout.write("\b" * index + " " * index + "\b" * index)
    sys.stdout.flush()  # flush the output

Keep in mind that this is a blocking process so you either have to do your loading checks within the for loop, or run your loading in a separate thread, or run this in a separate thread - it will keep running in a blocking mode as long as its local loading variable is set to True.

Sign up to request clarification or add additional context in comments.

5 Comments

can flush used to only remove last specific element? I mean if I print two lines in while loop till keyboard interrupt can it be used to remove only last line from it?
@mini - don't run it in mock shells, run it in a regular shell/terminal/command prompt/whatever as a script (python your_script.py). Debug/test environments are not designed to follow common terminal practices.
It Worked.You Are Awesome.But I want to Run It Shell.
@Gahan - you can blank out the whole line via sys.stdout.write("\r" + " " * 80 + "\r") in most terminals, assuming that the terminal width is 80 characters. You cannot (easily) backtrack multiple lines in most terminals and if you need to move all over the screen I suggest you to use the curses module. Check this answer for an example.
@mini - not being able to use backspace (\b) and carriage return (\r) control characters in IDLE is a well known, long standing bug (Issue #23220) and there's not much you can do about it. Keep in mind, tho, that most of the users of your text game will not even know what IDLE is, let alone use it. They will run your game the same way most Python programs are run - by running the Python interpreter in their OS default shell - and it will work in those cases.
6

Check This Module Keyboard with many features. Install It, perhaps with this command:

pip3 install keyboard

Then Write the following code in File textdot.py:

def text(text_to_print,num_of_dots,num_of_loops):
    from time import sleep
    import keyboard
    import sys
    shell = sys.stdout.shell
    shell.write(text_to_print,'stdout')
    dotes = int(num_of_dots) * '.'
    for last in range(0,num_of_loops):
        for dot in dotes:
            keyboard.write('.')
            sleep(0.1)
        for dot in dotes:
            keyboard.write('\x08')
            sleep(0.1)

Now Paste the file in Lib from your python folder.
Now you Can use it like following example:

import textdot
textdot.text('Loading',6,3)

Thanks

Comments

1

A bit late but for anyone else its not that complicated.

import os, time                                 #import os and time
def loading():                                  #make a function called loading
    spaces = 0                                      #making a variable to store the amount of spaces between the start and the "."
    while True:                                     #infinite loop
        print("\b "*spaces+".", end="", flush=True) #we are deleting however many spaces and making them " " then printing "."
        spaces = spaces+1                           #adding a space after each print
        time.sleep(0.2)                             #waiting 0.2 secconds before proceeding
        if (spaces>5):                              #if there are more than 5 spaces after adding one so meaning 5 spaces (if that makes sense)
            print("\b \b"*spaces, end="")           #delete the line
            spaces = 0                              #set the spaces back to 0

loading()                                       #call the function

Comments

0

I believe the following code is what you are looking for. Simply thread this in your script, and it will flash dots while the user is waiting.

################################################################################
"""
Use this to show progress in the terminal while other processes are runnning
                        - show_running.py -
"""
################################################################################
#import _thread as thread
import time, sys

def waiting(lenstr=20, zzz=0.5, dispstr='PROCESSING'):
    dots   = '.' * lenstr
    spaces = ' ' * lenstr
    print(dispstr.center(lenstr, '*'))
    while True:
        for i in range(lenstr):
            time.sleep(zzz)
            outstr = dots[:i] + spaces[i:]
            sys.stdout.write('\b' * lenstr + outstr)
            sys.stdout.flush()

        for i in range(lenstr, 0, -1):
            time.sleep(zzz)
            outstr = dots[:i] + spaces[i:]
            sys.stdout.write('\b' * lenstr + outstr)   
            sys.stdout.flush()  
#------------------------------------------------------------------------------#
if __name__ == '__main__':
    import _thread as thread
    from tkinter import *

    root = Tk()
    Label(root, text="I'm Waiting").pack()

    start = time.perf_counter()

    thread.start_new_thread(waiting, (20, 0.5))

    root.mainloop()

    finish = time.perf_counter()
    print('\nYour process took %.2f seconds to complete.' % (finish - start))

Comments

0

I had a similar issue. I thought a lot to solve my issue. The code should print "Loading" with dots.

import sys
import time

def print_loading_dots():
    while True:
        for i in range(4):
            sys.stdout.write('\r' + 'Loading' + '.' * i)
            sys.stdout.flush()
            time.sleep(0.5)
        sys.stdout.write("\033[K")
        sys.stdout.write("\r" + "Loading   ")


print_loading_dots()

Comments

0
import time

def print_loading(message, dots=3, loop=2):
    # Function to print loading animation with moving dots.
    # Parameters:
    # - message: The message to be displayed during the loading animation.
    # - dots (optional): The number of dots to be displayed during the animation. Default is 3.
    # - loop (optional): The number of times the loading animation will be repeated. Default is 2.
    
    for i in range(loop):
        for j in range(0, dots + 1):
            print(f"{message}{'.' * j}\033[K", end="\r")
            time.sleep(0.3)

        for j in range(dots - 1, 0, -1):
            print(f"{message}{'.' * j}\033[K", end="\r")
            time.sleep(0.3)

print_loading('Loading', dots=3, loop=1)

1 Comment

Answer needs supporting information Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.