Python how to make simple animated loading while process is running - python

This is pretty much what I have right now:
import time
import sys
done = 'false'
#here is the animation
def animate():
while done == 'false':
sys.stdout.write('\rloading |')
time.sleep(0.1)
sys.stdout.write('\rloading /')
time.sleep(0.1)
sys.stdout.write('\rloading -')
time.sleep(0.1)
sys.stdout.write('\rloading \\')
time.sleep(0.1)
sys.stdout.write('\rDone! ')
animate()
#long process here
done = 'false'
and I want to get it so that the "while" script would function independently, and it continues to the process, while the animation is going on until the end of the process signals the variable "done" to be 'false', stopping the animation and replacing it with "Done!". This method would be essentially running two scripts at once; is there a way to do it?

Use a thread:
import itertools
import threading
import time
import sys
done = False
#here is the animation
def animate():
for c in itertools.cycle(['|', '/', '-', '\\']):
if done:
break
sys.stdout.write('\rloading ' + c)
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\rDone! ')
t = threading.Thread(target=animate)
t.start()
#long process here
time.sleep(10)
done = True
I also made a couple of minor modifications to your animate() function, the only really important one was adding sys.stdout.flush() after the sys.stdout.write() calls.

Getting inspiration from the accepted answer, here's a useful class I wrote, printing a loader à la nodejs cli:
from itertools import cycle
from shutil import get_terminal_size
from threading import Thread
from time import sleep
class Loader:
def __init__(self, desc="Loading...", end="Done!", timeout=0.1):
"""
A loader-like context manager
Args:
desc (str, optional): The loader's description. Defaults to "Loading...".
end (str, optional): Final print. Defaults to "Done!".
timeout (float, optional): Sleep time between prints. Defaults to 0.1.
"""
self.desc = desc
self.end = end
self.timeout = timeout
self._thread = Thread(target=self._animate, daemon=True)
self.steps = ["⢿", "⣻", "⣽", "⣾", "⣷", "⣯", "⣟", "⡿"]
self.done = False
def start(self):
self._thread.start()
return self
def _animate(self):
for c in cycle(self.steps):
if self.done:
break
print(f"\r{self.desc} {c}", flush=True, end="")
sleep(self.timeout)
def __enter__(self):
self.start()
def stop(self):
self.done = True
cols = get_terminal_size((80, 20)).columns
print("\r" + " " * cols, end="", flush=True)
print(f"\r{self.end}", flush=True)
def __exit__(self, exc_type, exc_value, tb):
# handle exceptions with those variables ^
self.stop()
if __name__ == "__main__":
with Loader("Loading with context manager..."):
for i in range(10):
sleep(0.25)
loader = Loader("Loading with object...", "That was fast!", 0.05).start()
for i in range(10):
sleep(0.25)
loader.stop()
Also if you're willing to use an external library you might want to look into rich's console.status
from time import sleep
from rich.console import Console
console = Console()
tasks = [f"task {n}" for n in range(1, 11)]
with console.status("[bold green]Working on tasks...") as status:
while tasks:
task = tasks.pop(0)
sleep(1)
console.log(f"{task} complete")

I see this is a threading problem and not just an animated loading problem. Most the answers provided in this QA thread provides only a pseudocode and left the reader on their own.
Here is an answer I am trying to give using a working example of threading and animated loading.
The reader may modify in accordance to their needs.
Import python packages
import sys, time, threading
Define your process
# Here is an example of the process function:
def the_process_function():
n = 20
for i in range(n):
time.sleep(1)
sys.stdout.write('\r'+'loading... process '+str(i)+'/'+str(n)+' '+ '{:.2f}'.format(i/n*100)+'%')
sys.stdout.flush()
sys.stdout.write('\r'+'loading... finished \n')
Define your animated characters function
def animated_loading():
chars = "/—\|"
for char in chars:
sys.stdout.write('\r'+'loading...'+char)
time.sleep(.1)
sys.stdout.flush()
Define name dan target of your thread
the_process = threading.Thread(name='process', target=the_process_function)
Start the thread
the_process.start()
while the process is alive, call the animated_loading() function
while the_process.isAlive():
animated_loading()
The main steps are outlined in the commented out line.

Here is my code:
import time
import sys
print("Loading:")
#animation = ["10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"]
animation = ["[■□□□□□□□□□]","[■■□□□□□□□□]", "[■■■□□□□□□□]", "[■■■■□□□□□□]", "[■■■■■□□□□□]", "[■■■■■■□□□□]", "[■■■■■■■□□□]", "[■■■■■■■■□□]", "[■■■■■■■■■□]", "[■■■■■■■■■■]"]
for i in range(len(animation)):
time.sleep(0.2)
sys.stdout.write("\r" + animation[i % len(animation)])
sys.stdout.flush()
print("\n")

import sys, time, threading
def your_function_name() :
# do something here
def loadingAnimation(process) :
while process.isAlive() :
chars = "/—\|"
for char in chars:
sys.stdout.write('\r'+'loading '+char)
time.sleep(.1)
sys.stdout.flush()
loading_process = threading.Thread(target=your_function_name)
loading_process.start()
loadingAnimation(loading_process)
loading_process.join()

Try this one
import time
import sys
animation = "|/-\\"
for i in range(100):
time.sleep(0.1)
sys.stdout.write("\r" + animation[i % len(animation)])
sys.stdout.flush()
#do something
print("End!")

from time import sleep
k='#'
j=0
k='#'
def fixed_space(i,array):
g=(' '*len(str(len(array))))
g=g.replace(' ','',len(str(int(i))))
return g
def ani(i,array):
global k
#For accessing the global variables that are defined out of the function
global j
per=((i+1)*100)//len(array)
#To calculate percentage of completion of loop
c=per//5
#Integer division (the value 5 decides the length of the bar)
if c!=j:
#When ever the values of these 2 variables change add one # to the global variable k
k+='#'
y='['+k+' '+']'
#20 empty spaces (100/5)
y=y.replace(' ','',len(k))
#To make the size of the bar fixed ever time the length of k increases one ' ' will be removed
g=fixed_space(per,array)
#To fix at the same position
f=fixed_space(i,array)
print('Status : ',y,g+str(per)+'%',' ('+f+str(i+1)+' / '+str(len(array))+' ) ',end='\r')
#That same '\r' to clear previous text
j=c
array = range(100)
for i in array:
ani(i,array)
sleep(0.1)
my code is little bit messed up so feel free to update it

a simple one
from time import sleep #for delay
from itertools import cycle #for infinite cycling through a list
for i in cycle(["|", "/", "-", "\\"]):
print(i,end='\r') # '\r' clears the previous output
sleep(0.2)

Try it:
import threading, sys, time, webbrowser
def search_yt(inp_yt):
webbrowser.open(f"https://www.youtube.com/results?search_query={inp_yt}")
def loading(message="", round=1, _sleep=0.7, mark='-'):
no = round
hyphen = mark
space = ["", " ", " ", " ", " ", " ", " ", " ", " ", " "]
for loop in range(0, 10):
sys.stdout.write(f"\r{message} [{hyphen}{space[9 - loop]}]")
time.sleep(_sleep)
hyphen += mark
if no != 1:
loading(message, no -1 , _sleep, mark)
t1 = threading.Thread(target=loading, args=("hello",1, 0.5,"=",))#loading()
t2 = threading.Thread(target=search_yt, args=("python",))
t1.start()
t2.start()

Its all done with a few lines of code:
import time
import os
anime = ["|", "/", "-", "\\"]
done = False
while done is False:
for i in anime:
print('Please wait while system is Loading...', i)
os.system('clear')
time.sleep(0.1)
Tested and working successfully in the terminal.

Related

Python - How can I run two dependant funtions at the same time?

I have two funtions, one runs increasing by one a number, and the other needs to capture the number that is running the first function every 5 seconds, so that when I capture the first number is 0, the sencond one is 10, the next one is 15, and so on... this is simulating the first function as a sensor. My code is as follows:
import time
import threading
from threading import Thread
def numero(i=0):
while True:
i = i + 1
time.sleep(1)
#print i
def capturar():
while True:
posicion = numero()
time.sleep(5)
print posicion
if __name__ == '__main__':
Thread(target = capturar()).start()
Thread(target = numero()).start()
When I run this code, it keeps in the first function, how can I get this run correctly and obtain the capture of the series of numbers every 5 seconds?
There are several mistakes in your code:
i is not in scope for capturar
you execute capturar and numero instead of handing the functions themselves to Thread
As Matt Clark commented, you call numero from capturar, which never returns, so capturar can't even do one full loop.
To help with the first one, the easiest solution is to wrap the functions into a class, and make i into an instance state (as an attribute). The second one merely requires you to remove the extra parentheses. The third one is resolved with the first one, as there is no function call required any more to fetch the counter state.
This should do what you want:
import time
from threading import Thread
class Contador:
def __init__(self, comienzo = 0):
self.numero = comienzo
def producir(self):
while True:
self.numero += 1
time.sleep(1)
def capturar(self):
while True:
posicion = self.numero
time.sleep(5)
print posicion
if __name__ == '__main__':
c = Contador()
Thread(target = c.capturar).start()
Thread(target = c.producir).start()
Thank you Amadan, the soution that you share is working perfectlym but when I tried to pull it into the real sensor (GPS), I am getting only "0"
import gps
import itertools
import json
import os
import portdetect
import time
import serial
from threading import Thread
(puerto1, puerto2) = portdetect.detectar_puerto()
print puerto1, puerto2
port = serial.Serial(puerto1, 115200, timeout=1)
os.system('sudo systemctl stop gpsd.socket')
time.sleep(2)
os.system('sudo systemctl disable gpsd.socket')
time.sleep(2)
comando = 'sudo gpsd ' + puerto2 + ' -F /var/run/gpsd.sock'
os.system(str(comando))
#print str(comando)
# Listen on port 2947 (gpsd) of localhost
session = gps.gps("localhost", "2947")
session.stream(gps.WATCH_ENABLE | gps.WATCH_NEWSTYLE)
class Contador:
def __init__(self, comienzo = 0):
self.raw_datos = comienzo
def leergps(self):
while True:
try:
report = session.next()
# Wait for a 'TPV' report and display the current time
# To see all report data, uncomment the line below
# print report
if report['class'] == 'TPV':
if hasattr(report, 'time') or hasattr(report, 'lat') or hasattr(report, 'lon') or hasattr(report,
'speed'):
datos = [report.time, report.lat, report.lon, report.speed]
clave = ['tiempo', 'lat', 'lon', 'speed']
diccionario = dict(itertools.izip(clave, datos))
self.raw_datos = (json.dumps(diccionario))
# print raw_datos
return self.raw_datos
else:
return report['class']
except:
print "Error de coordenadas"
def capturar(self):
while True:
posicion = self.raw_datos
time.sleep(5)
print posicion
if __name__ == '__main__':
c = Contador()
Thread(target = c.capturar).start()
Thread(target = c.leergps()).start()
I am trying only to pull the "raw data obtained every 5 seconds, but I am not achieving this"

Print array data 1 by 1 sleeping between each iteration? [duplicate]

Is there a way to print a spinning cursor in a terminal using Python?
Something like this, assuming your terminal handles \b
import sys
import time
def spinning_cursor():
while True:
for cursor in '|/-\\':
yield cursor
spinner = spinning_cursor()
for _ in range(50):
sys.stdout.write(next(spinner))
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\b')
Easy to use API (this will run the spinner in a separate thread):
import sys
import time
import threading
class Spinner:
busy = False
delay = 0.1
#staticmethod
def spinning_cursor():
while 1:
for cursor in '|/-\\': yield cursor
def __init__(self, delay=None):
self.spinner_generator = self.spinning_cursor()
if delay and float(delay): self.delay = delay
def spinner_task(self):
while self.busy:
sys.stdout.write(next(self.spinner_generator))
sys.stdout.flush()
time.sleep(self.delay)
sys.stdout.write('\b')
sys.stdout.flush()
def __enter__(self):
self.busy = True
threading.Thread(target=self.spinner_task).start()
def __exit__(self, exception, value, tb):
self.busy = False
time.sleep(self.delay)
if exception is not None:
return False
Now use it in a with block anywhere in the code:
with Spinner():
# ... some long-running operations
# time.sleep(3)
A nice pythonic way is to use itertools.cycle:
import itertools, sys
spinner = itertools.cycle(['-', '/', '|', '\\'])
while True:
sys.stdout.write(next(spinner)) # write the next character
sys.stdout.flush() # flush stdout buffer (actual character display)
sys.stdout.write('\b') # erase the last written char
Also, you might want to use threading to display the spinner during a long function call, as in http://www.interclasse.com/scripts/spin.php
For completeness I want to add the great package halo. It offers a lot of preset spinners and higher level customization options.
Extract from their readme
from halo import Halo
spinner = Halo(text='Loading', spinner='dots')
spinner.start()
# Run time consuming work here
# You can also change properties for spinner as and when you want
spinner.stop()
Alternatively, you can use halo with Python's with statement:
from halo import Halo
with Halo(text='Loading', spinner='dots'):
# Run time consuming work here
Finally, you can use halo as a decorator:
from halo import Halo
#Halo(text='Loading', spinner='dots')
def long_running_function():
# Run time consuming work here
pass
long_running_function()
A solution:
import sys
import time
print "processing...\\",
syms = ['\\', '|', '/', '-']
bs = '\b'
for _ in range(10):
for sym in syms:
sys.stdout.write("\b%s" % sym)
sys.stdout.flush()
time.sleep(.5)
The key is to use the backspace character '\b' and flush stdout.
Improved version from #Victor Moyseenko
as the original version had few issues
was leaving spinner's characters after spinning is complete
and sometimes lead to removing following output's first character too
avoids a rare race condition by putting threading.Lock() on output
falls back to simpler output when no tty is available (no spinning)
import sys
import threading
import itertools
import time
class Spinner:
def __init__(self, message, delay=0.1):
self.spinner = itertools.cycle(['-', '/', '|', '\\'])
self.delay = delay
self.busy = False
self.spinner_visible = False
sys.stdout.write(message)
def write_next(self):
with self._screen_lock:
if not self.spinner_visible:
sys.stdout.write(next(self.spinner))
self.spinner_visible = True
sys.stdout.flush()
def remove_spinner(self, cleanup=False):
with self._screen_lock:
if self.spinner_visible:
sys.stdout.write('\b')
self.spinner_visible = False
if cleanup:
sys.stdout.write(' ') # overwrite spinner with blank
sys.stdout.write('\r') # move to next line
sys.stdout.flush()
def spinner_task(self):
while self.busy:
self.write_next()
time.sleep(self.delay)
self.remove_spinner()
def __enter__(self):
if sys.stdout.isatty():
self._screen_lock = threading.Lock()
self.busy = True
self.thread = threading.Thread(target=self.spinner_task)
self.thread.start()
def __exit__(self, exception, value, tb):
if sys.stdout.isatty():
self.busy = False
self.remove_spinner(cleanup=True)
else:
sys.stdout.write('\r')
example of usage of the Spinner class above:
with Spinner("just waiting a bit.. "):
time.sleep(3)
uploaded code to https://github.com/Tagar/stuff/blob/master/spinner.py
Nice, simple, and clean...
while True:
for i in '|\\-/':
print('\b' + i, end='')
Sure, it's possible. It's just a question of printing the backspace character (\b) in between the four characters that would make the "cursor" look like it's spinning ( -, \, |, /).
I have found py-spin package on GitHub. It has many nice spinning Styles. Here are some sample about how to use, Spin1 is the \-/ style:
from __future__ import print_function
import time
from pyspin.spin import make_spin, Spin1
# Choose a spin style and the words when showing the spin.
#make_spin(Spin1, "Downloading...")
def download_video():
time.sleep(10)
if __name__ == '__main__':
print("I'm going to download a video, and it'll cost much time.")
download_video()
print("Done!")
time.sleep(0.1)
It is also possible to control the spin manualy:
from __future__ import print_function
import sys
import time
from pyspin.spin import Spin1, Spinner
# Choose a spin style.
spin = Spinner(Spin1)
# Spin it now.
for i in range(50):
print(u"\r{0}".format(spin.next()), end="")
sys.stdout.flush()
time.sleep(0.1)
Other styles in the below gif.
Grab the awesome progressbar module - http://code.google.com/p/python-progressbar/
use RotatingMarker.
I built a generic Singleton, shared by the entire application
from itertools import cycle
import threading
import time
class Spinner:
__default_spinner_symbols_list = ['|-----|', '|#----|', '|-#---|', '|--#--|', '|---#-|', '|----#|']
def __init__(self, spinner_symbols_list: [str] = None):
spinner_symbols_list = spinner_symbols_list if spinner_symbols_list else Spinner.__default_spinner_symbols_list
self.__screen_lock = threading.Event()
self.__spinner = cycle(spinner_symbols_list)
self.__stop_event = False
self.__thread = None
def get_spin(self):
return self.__spinner
def start(self, spinner_message: str):
self.__stop_event = False
time.sleep(0.3)
def run_spinner(message):
while not self.__stop_event:
print("\r{message} {spinner}".format(message=message, spinner=next(self.__spinner)), end="")
time.sleep(0.3)
self.__screen_lock.set()
self.__thread = threading.Thread(target=run_spinner, args=(spinner_message,), daemon=True)
self.__thread.start()
def stop(self):
self.__stop_event = True
if self.__screen_lock.is_set():
self.__screen_lock.wait()
self.__screen_lock.clear()
print("\r", end="")
print("\r", end="")
if __name__ == '__main__':
import time
# Testing
spinner = Spinner()
spinner.start("Downloading")
# Make actions
time.sleep(5) # Simulate a process
#
spinner.stop()
You can write '\r\033[K' to clear the current line. And the following is a example modified from #nos.
import sys
import time
def spinning_cursor():
while True:
for cursor in '|/-\\':
yield cursor
spinner = spinning_cursor()
for _ in range(1, 10):
content = f'\r{next(spinner)} Downloading...'
print(content, end="")
time.sleep(0.1)
print('\r\033[K', end="")
For anyone who interested in nodejs, I also write a nodejs example.
function* makeSpinner(start = 0, end = 100, step = 1) {
let iterationCount = 0;
while (true) {
for (const char of '|/-\\') {
yield char;
}
}
return iterationCount;
}
async function sleep(seconds) {
return new Promise((resolve) => {
setTimeout(resolve, seconds * 1000);
});
}
(async () => {
const spinner = makeSpinner();
for (let i = 0; i < 10; i++) {
content = `\r${spinner.next().value} Downloading...`;
process.stdout.write(content);
await sleep(0.1);
process.stdout.write('\r\033[K');
}
})();
curses module. i'd have a look at the addstr() and addch() functions. Never used it though.
For more advanced console manipulations, on unix you can use the curses python module, and on windows, you can use WConio which provides equivalent functionality of the curses library.
#!/usr/bin/env python
import sys
chars = '|/-\\'
for i in xrange(1,1000):
for c in chars:
sys.stdout.write(c)
sys.stdout.write('\b')
sys.stdout.flush()
CAVEATS:
In my experience this doesn't work in all terminals. A more robust way to do this under Unix/Linux, be it more complicated is to use the curses module, which doesn't work under Windows.
You probably want to slow it down some how with actual processing that is going on in the background.
Here ya go - simple and clear.
import sys
import time
idx = 0
cursor = ['|','/','-','\\'] #frames of an animated cursor
while True:
sys.stdout.write(cursor[idx])
sys.stdout.write('\b')
idx = idx + 1
if idx > 3:
idx = 0
time.sleep(.1)
Crude but simple solution:
import sys
import time
cursor = ['|','/','-','\\']
for count in range(0,1000):
sys.stdout.write('\b{}'.format(cursor[count%4]))
sys.stdout.flush()
# replace time.sleep() with some logic
time.sleep(.1)
There are obvious limitations, but again, crude.
I propose a solution using decorators
from itertools import cycle
import functools
import threading
import time
def spinner(message, spinner_symbols: list = None):
spinner_symbols = spinner_symbols or list("|/-\\")
spinner_symbols = cycle(spinner_symbols)
global spinner_event
spinner_event = True
def start():
global spinner_event
while spinner_event:
symbol = next(spinner_symbols)
print("\r{message} {symbol}".format(message=message, symbol=symbol), end="")
time.sleep(0.3)
def stop():
global spinner_event
spinner_event = False
print("\r", end="")
def external(fct):
#functools.wraps(fct)
def wrapper(*args):
spinner_thread = threading.Thread(target=start, daemon=True)
spinner_thread.start()
result = fct(*args)
stop()
spinner_thread.join()
return result
return wrapper
return external
Simple usage
#spinner("Downloading")
def f():
time.sleep(10)
import sys
def DrowWaitCursor(counter):
if counter % 4 == 0:
print("/",end = "")
elif counter % 4 == 1:
print("-",end = "")
elif counter % 4 == 2:
print("\\",end = "")
elif counter % 4 == 3:
print("|",end = "")
sys.stdout.flush()
sys.stdout.write('\b')
This can be also another solution using a function with a parameter.
I just started with python about a week ago and found this posting. I've combined a bit of what I found here with stuff I learned about threads and queues elsewhere to provide a much better implementation in my opinion. In my solution, writing to the screen is handled by a thread that checks a queue for content. If that queue has content, the cursor spinning thread knows to stop. On the flipside, the cursor spinning thread uses a queue as a lock so the printing thread knows not to print until a full pass of the spinner code is complete. This prevents race conditions and a lot of excess code people are using to keep the console clean.
See below:
import threading, queue, itertools, sys, time # all required for my version of spinner
import datetime #not required for spinning cursor solution, only my example
console_queue = queue.Queue() # this queue should be initialized before functions
screenlock = queue.Queue() # this queue too...
def main():
threading.Thread(target=spinner).start()
threading.Thread(target=consoleprint).start()
while True:
# instead of invoking print or stdout.write, we just add items to the console_queue
# The next three lines are an example of my code in practice.
time.sleep(.5) # wait half a second
currenttime = "[" + datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S") + "] "
console_queue.put(currenttime) # The most important part. Substitute your print and stdout functions with this.
def spinner(console_queue = console_queue, screenlock = screenlock):
spinnerlist = itertools.cycle(['|', '/', '-', '\\'])
while True:
if console_queue.empty():
screenlock.put("locked")
sys.stdout.write(next(spinnerlist))
sys.stdout.flush()
sys.stdout.write('\b')
sys.stdout.flush()
screenlock.get()
time.sleep(.1)
def consoleprint(console_queue = console_queue, screenlock = screenlock):
while True:
if not console_queue.empty():
while screenlock.empty() == False:
time.sleep(.1)
sys.stdout.flush()
print(console_queue.get())
sys.stdout.flush()
if __name__ == "__main__":
main()
Having said all I said and written all I've written, I've only been doing python stuff for a week. If there are cleaner ways of doing this or I missed some best practices I'd love to learn. Thanks.
import requests
import time
import sys
weathercity = input("What city are you in? ")
weather = requests.get('http://api.openweathermap.org/data/2.5/weather?q='+weathercity+'&appid=886705b4c1182eb1c69f28eb8c520e20')
url = ('http://api.openweathermap.org/data/2.5/weather?q='+weathercity+'&appid=886705b4c1182eb1c69f28eb8c520e20')
def spinning_cursor():
while True:
for cursor in '|/-\\':
yield cursor
data = weather.json()
temp = data['main']['temp']
description = data['weather'][0]['description']
weatherprint ="In {}, it is currently {}°C with {}."
spinner = spinning_cursor()
for _ in range(25):
sys.stdout.write(next(spinner))
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\b')
convert = int(temp - 273.15)
print(weatherprint.format(weathercity, convert, description))
if you wanna python text spinner you can look picture
Simple:print_spinner("Hayatta en hakiki mürşit ilimdir.")
Here is the simplest loading spinner for python:
import time
spin=["loading...... ", "|", "/","-", "\"]
for i in spin:
print("\b"+i, end=" ")
time.sleep (0.2)
Output:
loading...... |

Most efficient way to perform a deferred action in Python

Consider a system where I have events coming in at unpredictable points in time. I want to be able to perform a "deferred" action that executes a fixed amount of time, X units, after the last event has come in. An event is considered "last" if it is the only event to have occurred in the last X units of time. What is the most efficient way to do this in Python?
One solution I have considered is using a threading.Event:
# This solution has the drawback that the deferred event may actually occur
# up to 2*X units of time after the last event.
# Also, it kinda sucks that the thread is basically polling once the first
# event comes in.
from threading import Thread
from threading import Event
import time
import sys
evt = Event()
die = False
X = 1
def thread_func_event():
while True:
evt.wait()
if die:
break
while True:
evt.clear()
time.sleep(X)
if not evt.is_set():
# No more events came in. Good.
break
# Looks like more events came in. Let's try again.
if die:
return
print('Deferred action performed.')
sys.stdout.flush()
def event_occurred():
evt.set()
t = Thread(target=thread_func_event)
t.start()
for _ in range(0, 1000000):
event_occurred()
print('First batch of events done.')
sys.stdout.flush()
time.sleep(3)
for _ in range(0, 1000000):
event_occurred()
print('Second batch of events done.')
sys.stdout.flush()
time.sleep(3)
die = True
evt.set()
t.join()
I've done something like this before.
import threading
import time
class waiter(object):
def __init__(self, action, delay = 0.5, *args, **kwargs):
self.action_lockout_timeout = threading.Thread()
self.action_lockout_event = threading.Event()
self.action = action
self.delay = delay
self.action_prevent()
def action_prevent(self):
def action_enable():
self.action_lockout_event.wait(self.delay)
if not self.action_lockout_event._Event__flag:
self.action()
if self.action_lockout_timeout.isAlive():
self.action_lockout_event.set()
self.action_lockout_timeout.join()
self.action_lockout_event.clear()
self.action_lockout_timeout = threading.Thread(target = action_enable)
self.action_lockout_timeout.setDaemon(True)
self.action_lockout_timeout.start()
def thanks():
print("Person 2: Thank you ...")
polite = waiter(thanks, 3)
print("Person 1: After you")
polite.action_prevent()
time.sleep(2)
print("Person 2: No, after you")
polite.action_prevent()
time.sleep(2)
print("Person 1: No I insist")
polite.action_prevent()
time.sleep(2)
print("Person 2: But it would be rude")
polite.action_prevent()
time.sleep(2)
print("---Akward Silence---")
time.sleep(2)
If you want to run a function with arguments, just wrap it with a lambda expression.
def thanks(person):
print("%s: Thank you ..." % person)
polite = waiter(lambda: thanks("Person 2"), 3)
EDIT:
Turns out that threading.Event is pretty slow. Here's a solution that replaces the Event with time.sleep and a bool. It also uses __slots__ to speed up attribute accesses
import sys
import threading
import time
class waiter(object):
__slots__ = \
[
"action",
"delay",
"undelayed",
"delay_timeout",
]
def __init__(self, action, delay = 0.5, *args, **kwargs):
self.action = action
self.delay = delay
self.undelayed = False
self.delay_timeout = threading.Thread(target = self.action_enable)
self.delay_timeout.start()
def action_prevent(self):
self.undelayed = False
def action_enable(self):
while True:
time.sleep(self.delay)
if self.undelayed:
self.action()
break
else:
self.undelayed = True
def thanks():
print("Person 2: Thank you ...")
polite = waiter(thanks, 1)
for _ in range(0, 1000000):
polite.action_prevent()
print("First batch of events done.")
time.sleep(2)

kill a function after a certain time in windows

I've read a lot of posts about using threads, subprocesses, etc.. A lot of it seems over complicated for what I'm trying to do...
All I want to do is stop executing a function after X amount of time has elapsed.
def big_loop(bob):
x = bob
start = time.time()
while True:
print time.time()-start
This function is an endless loop that never throws any errors or exceptions, period.
I"m not sure the difference between "commands, shells, subprocesses, threads, etc.." and this function, which is why I'm having trouble manipulating subprocesses.
I found this code here, and tried it but as you can see it keeps printing after 10 seconds have elapsed:
import time
import threading
import subprocess as sub
import time
class RunCmd(threading.Thread):
def __init__(self, cmd, timeout):
threading.Thread.__init__(self)
self.cmd = cmd
self.timeout = timeout
def run(self):
self.p = sub.Popen(self.cmd)
self.p.wait()
def Run(self):
self.start()
self.join(self.timeout)
if self.is_alive():
self.p.terminate()
self.join()
def big_loop(bob):
x = bob
start = time.time()
while True:
print time.time()-start
RunCmd(big_loop('jimijojo'), 10).Run() #supposed to quit after 10 seconds, but doesn't
x = raw_input('DONEEEEEEEEEEEE')
What's a simple way this function can be killed. As you can see in my attempt above, it doesn't terminate after 20 seconds and just keeps on going...
***OH also, I've read about using signal, but I"m on windows so I can't use the alarm feature.. (python 2.7)
**assume the "infinitely running function" can't be manipulated or changed to be non-infinite, if I could change the function, well I'd just change it to be non infinite wouldn't I?
Here are some similar questions, which I haven't able to port over their code to work with my simple function:
Perhaps you can?
Python: kill or terminate subprocess when timeout
signal.alarm replacement in Windows [Python]
Ok I tried an answer I received, it works.. but how can I use it if I remove the if __name__ == "__main__": statement? When I remove this statement, the loop never ends as it did before..
import multiprocessing
import Queue
import time
def infinite_loop_function(bob):
var = bob
start = time.time()
while True:
time.sleep(1)
print time.time()-start
print 'this statement will never print'
def wrapper(queue, bob):
result = infinite_loop_function(bob)
queue.put(result)
queue.close()
#if __name__ == "__main__":
queue = multiprocessing.Queue(1) # Maximum size is 1
proc = multiprocessing.Process(target=wrapper, args=(queue, 'var'))
proc.start()
# Wait for TIMEOUT seconds
try:
timeout = 10
result = queue.get(True, timeout)
except Queue.Empty:
# Deal with lack of data somehow
result = None
finally:
proc.terminate()
print 'running other code, now that that infinite loop has been defeated!'
print 'bla bla bla'
x = raw_input('done')
Use the building blocks in the multiprocessing module:
import multiprocessing
import Queue
TIMEOUT = 5
def big_loop(bob):
import time
time.sleep(4)
return bob*2
def wrapper(queue, bob):
result = big_loop(bob)
queue.put(result)
queue.close()
def run_loop_with_timeout():
bob = 21 # Whatever sensible value you need
queue = multiprocessing.Queue(1) # Maximum size is 1
proc = multiprocessing.Process(target=wrapper, args=(queue, bob))
proc.start()
# Wait for TIMEOUT seconds
try:
result = queue.get(True, TIMEOUT)
except Queue.Empty:
# Deal with lack of data somehow
result = None
finally:
proc.terminate()
# Process data here, not in try block above, otherwise your process keeps running
print result
if __name__ == "__main__":
run_loop_with_timeout()
You could also accomplish this with a Pipe/Connection pair, but I'm not familiar with their API. Change the sleep time or TIMEOUT to check the behaviour for either case.
There is no straightforward way to kill a function after a certain amount of time without running the function in a separate process. A better approach would probably be to rewrite the function so that it returns after a specified time:
import time
def big_loop(bob, timeout):
x = bob
start = time.time()
end = start + timeout
while time.time() < end:
print time.time() - start
# Do more stuff here as needed
Can't you just return from the loop?
start = time.time()
endt = start + 30
while True:
now = time.time()
if now > endt:
return
else:
print end - start
import os,signal,time
cpid = os.fork()
if cpid == 0:
while True:
# do stuff
else:
time.sleep(10)
os.kill(cpid, signal.SIGKILL)
You can also check in the loop of a thread for an event, which is more portable and flexible as it allows other reactions than brute killing. However, this approach fails if # do stuff can take time (or even wait forever on some event).

How to create a spinning command line cursor?

Is there a way to print a spinning cursor in a terminal using Python?
Something like this, assuming your terminal handles \b
import sys
import time
def spinning_cursor():
while True:
for cursor in '|/-\\':
yield cursor
spinner = spinning_cursor()
for _ in range(50):
sys.stdout.write(next(spinner))
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\b')
Easy to use API (this will run the spinner in a separate thread):
import sys
import time
import threading
class Spinner:
busy = False
delay = 0.1
#staticmethod
def spinning_cursor():
while 1:
for cursor in '|/-\\': yield cursor
def __init__(self, delay=None):
self.spinner_generator = self.spinning_cursor()
if delay and float(delay): self.delay = delay
def spinner_task(self):
while self.busy:
sys.stdout.write(next(self.spinner_generator))
sys.stdout.flush()
time.sleep(self.delay)
sys.stdout.write('\b')
sys.stdout.flush()
def __enter__(self):
self.busy = True
threading.Thread(target=self.spinner_task).start()
def __exit__(self, exception, value, tb):
self.busy = False
time.sleep(self.delay)
if exception is not None:
return False
Now use it in a with block anywhere in the code:
with Spinner():
# ... some long-running operations
# time.sleep(3)
A nice pythonic way is to use itertools.cycle:
import itertools, sys
spinner = itertools.cycle(['-', '/', '|', '\\'])
while True:
sys.stdout.write(next(spinner)) # write the next character
sys.stdout.flush() # flush stdout buffer (actual character display)
sys.stdout.write('\b') # erase the last written char
Also, you might want to use threading to display the spinner during a long function call, as in http://www.interclasse.com/scripts/spin.php
For completeness I want to add the great package halo. It offers a lot of preset spinners and higher level customization options.
Extract from their readme
from halo import Halo
spinner = Halo(text='Loading', spinner='dots')
spinner.start()
# Run time consuming work here
# You can also change properties for spinner as and when you want
spinner.stop()
Alternatively, you can use halo with Python's with statement:
from halo import Halo
with Halo(text='Loading', spinner='dots'):
# Run time consuming work here
Finally, you can use halo as a decorator:
from halo import Halo
#Halo(text='Loading', spinner='dots')
def long_running_function():
# Run time consuming work here
pass
long_running_function()
A solution:
import sys
import time
print "processing...\\",
syms = ['\\', '|', '/', '-']
bs = '\b'
for _ in range(10):
for sym in syms:
sys.stdout.write("\b%s" % sym)
sys.stdout.flush()
time.sleep(.5)
The key is to use the backspace character '\b' and flush stdout.
Improved version from #Victor Moyseenko
as the original version had few issues
was leaving spinner's characters after spinning is complete
and sometimes lead to removing following output's first character too
avoids a rare race condition by putting threading.Lock() on output
falls back to simpler output when no tty is available (no spinning)
import sys
import threading
import itertools
import time
class Spinner:
def __init__(self, message, delay=0.1):
self.spinner = itertools.cycle(['-', '/', '|', '\\'])
self.delay = delay
self.busy = False
self.spinner_visible = False
sys.stdout.write(message)
def write_next(self):
with self._screen_lock:
if not self.spinner_visible:
sys.stdout.write(next(self.spinner))
self.spinner_visible = True
sys.stdout.flush()
def remove_spinner(self, cleanup=False):
with self._screen_lock:
if self.spinner_visible:
sys.stdout.write('\b')
self.spinner_visible = False
if cleanup:
sys.stdout.write(' ') # overwrite spinner with blank
sys.stdout.write('\r') # move to next line
sys.stdout.flush()
def spinner_task(self):
while self.busy:
self.write_next()
time.sleep(self.delay)
self.remove_spinner()
def __enter__(self):
if sys.stdout.isatty():
self._screen_lock = threading.Lock()
self.busy = True
self.thread = threading.Thread(target=self.spinner_task)
self.thread.start()
def __exit__(self, exception, value, tb):
if sys.stdout.isatty():
self.busy = False
self.remove_spinner(cleanup=True)
else:
sys.stdout.write('\r')
example of usage of the Spinner class above:
with Spinner("just waiting a bit.. "):
time.sleep(3)
uploaded code to https://github.com/Tagar/stuff/blob/master/spinner.py
Nice, simple, and clean...
while True:
for i in '|\\-/':
print('\b' + i, end='')
Sure, it's possible. It's just a question of printing the backspace character (\b) in between the four characters that would make the "cursor" look like it's spinning ( -, \, |, /).
I have found py-spin package on GitHub. It has many nice spinning Styles. Here are some sample about how to use, Spin1 is the \-/ style:
from __future__ import print_function
import time
from pyspin.spin import make_spin, Spin1
# Choose a spin style and the words when showing the spin.
#make_spin(Spin1, "Downloading...")
def download_video():
time.sleep(10)
if __name__ == '__main__':
print("I'm going to download a video, and it'll cost much time.")
download_video()
print("Done!")
time.sleep(0.1)
It is also possible to control the spin manualy:
from __future__ import print_function
import sys
import time
from pyspin.spin import Spin1, Spinner
# Choose a spin style.
spin = Spinner(Spin1)
# Spin it now.
for i in range(50):
print(u"\r{0}".format(spin.next()), end="")
sys.stdout.flush()
time.sleep(0.1)
Other styles in the below gif.
Grab the awesome progressbar module - http://code.google.com/p/python-progressbar/
use RotatingMarker.
I built a generic Singleton, shared by the entire application
from itertools import cycle
import threading
import time
class Spinner:
__default_spinner_symbols_list = ['|-----|', '|#----|', '|-#---|', '|--#--|', '|---#-|', '|----#|']
def __init__(self, spinner_symbols_list: [str] = None):
spinner_symbols_list = spinner_symbols_list if spinner_symbols_list else Spinner.__default_spinner_symbols_list
self.__screen_lock = threading.Event()
self.__spinner = cycle(spinner_symbols_list)
self.__stop_event = False
self.__thread = None
def get_spin(self):
return self.__spinner
def start(self, spinner_message: str):
self.__stop_event = False
time.sleep(0.3)
def run_spinner(message):
while not self.__stop_event:
print("\r{message} {spinner}".format(message=message, spinner=next(self.__spinner)), end="")
time.sleep(0.3)
self.__screen_lock.set()
self.__thread = threading.Thread(target=run_spinner, args=(spinner_message,), daemon=True)
self.__thread.start()
def stop(self):
self.__stop_event = True
if self.__screen_lock.is_set():
self.__screen_lock.wait()
self.__screen_lock.clear()
print("\r", end="")
print("\r", end="")
if __name__ == '__main__':
import time
# Testing
spinner = Spinner()
spinner.start("Downloading")
# Make actions
time.sleep(5) # Simulate a process
#
spinner.stop()
You can write '\r\033[K' to clear the current line. And the following is a example modified from #nos.
import sys
import time
def spinning_cursor():
while True:
for cursor in '|/-\\':
yield cursor
spinner = spinning_cursor()
for _ in range(1, 10):
content = f'\r{next(spinner)} Downloading...'
print(content, end="")
time.sleep(0.1)
print('\r\033[K', end="")
For anyone who interested in nodejs, I also write a nodejs example.
function* makeSpinner(start = 0, end = 100, step = 1) {
let iterationCount = 0;
while (true) {
for (const char of '|/-\\') {
yield char;
}
}
return iterationCount;
}
async function sleep(seconds) {
return new Promise((resolve) => {
setTimeout(resolve, seconds * 1000);
});
}
(async () => {
const spinner = makeSpinner();
for (let i = 0; i < 10; i++) {
content = `\r${spinner.next().value} Downloading...`;
process.stdout.write(content);
await sleep(0.1);
process.stdout.write('\r\033[K');
}
})();
curses module. i'd have a look at the addstr() and addch() functions. Never used it though.
For more advanced console manipulations, on unix you can use the curses python module, and on windows, you can use WConio which provides equivalent functionality of the curses library.
#!/usr/bin/env python
import sys
chars = '|/-\\'
for i in xrange(1,1000):
for c in chars:
sys.stdout.write(c)
sys.stdout.write('\b')
sys.stdout.flush()
CAVEATS:
In my experience this doesn't work in all terminals. A more robust way to do this under Unix/Linux, be it more complicated is to use the curses module, which doesn't work under Windows.
You probably want to slow it down some how with actual processing that is going on in the background.
Here ya go - simple and clear.
import sys
import time
idx = 0
cursor = ['|','/','-','\\'] #frames of an animated cursor
while True:
sys.stdout.write(cursor[idx])
sys.stdout.write('\b')
idx = idx + 1
if idx > 3:
idx = 0
time.sleep(.1)
Crude but simple solution:
import sys
import time
cursor = ['|','/','-','\\']
for count in range(0,1000):
sys.stdout.write('\b{}'.format(cursor[count%4]))
sys.stdout.flush()
# replace time.sleep() with some logic
time.sleep(.1)
There are obvious limitations, but again, crude.
I propose a solution using decorators
from itertools import cycle
import functools
import threading
import time
def spinner(message, spinner_symbols: list = None):
spinner_symbols = spinner_symbols or list("|/-\\")
spinner_symbols = cycle(spinner_symbols)
global spinner_event
spinner_event = True
def start():
global spinner_event
while spinner_event:
symbol = next(spinner_symbols)
print("\r{message} {symbol}".format(message=message, symbol=symbol), end="")
time.sleep(0.3)
def stop():
global spinner_event
spinner_event = False
print("\r", end="")
def external(fct):
#functools.wraps(fct)
def wrapper(*args):
spinner_thread = threading.Thread(target=start, daemon=True)
spinner_thread.start()
result = fct(*args)
stop()
spinner_thread.join()
return result
return wrapper
return external
Simple usage
#spinner("Downloading")
def f():
time.sleep(10)
import sys
def DrowWaitCursor(counter):
if counter % 4 == 0:
print("/",end = "")
elif counter % 4 == 1:
print("-",end = "")
elif counter % 4 == 2:
print("\\",end = "")
elif counter % 4 == 3:
print("|",end = "")
sys.stdout.flush()
sys.stdout.write('\b')
This can be also another solution using a function with a parameter.
I just started with python about a week ago and found this posting. I've combined a bit of what I found here with stuff I learned about threads and queues elsewhere to provide a much better implementation in my opinion. In my solution, writing to the screen is handled by a thread that checks a queue for content. If that queue has content, the cursor spinning thread knows to stop. On the flipside, the cursor spinning thread uses a queue as a lock so the printing thread knows not to print until a full pass of the spinner code is complete. This prevents race conditions and a lot of excess code people are using to keep the console clean.
See below:
import threading, queue, itertools, sys, time # all required for my version of spinner
import datetime #not required for spinning cursor solution, only my example
console_queue = queue.Queue() # this queue should be initialized before functions
screenlock = queue.Queue() # this queue too...
def main():
threading.Thread(target=spinner).start()
threading.Thread(target=consoleprint).start()
while True:
# instead of invoking print or stdout.write, we just add items to the console_queue
# The next three lines are an example of my code in practice.
time.sleep(.5) # wait half a second
currenttime = "[" + datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S") + "] "
console_queue.put(currenttime) # The most important part. Substitute your print and stdout functions with this.
def spinner(console_queue = console_queue, screenlock = screenlock):
spinnerlist = itertools.cycle(['|', '/', '-', '\\'])
while True:
if console_queue.empty():
screenlock.put("locked")
sys.stdout.write(next(spinnerlist))
sys.stdout.flush()
sys.stdout.write('\b')
sys.stdout.flush()
screenlock.get()
time.sleep(.1)
def consoleprint(console_queue = console_queue, screenlock = screenlock):
while True:
if not console_queue.empty():
while screenlock.empty() == False:
time.sleep(.1)
sys.stdout.flush()
print(console_queue.get())
sys.stdout.flush()
if __name__ == "__main__":
main()
Having said all I said and written all I've written, I've only been doing python stuff for a week. If there are cleaner ways of doing this or I missed some best practices I'd love to learn. Thanks.
import requests
import time
import sys
weathercity = input("What city are you in? ")
weather = requests.get('http://api.openweathermap.org/data/2.5/weather?q='+weathercity+'&appid=886705b4c1182eb1c69f28eb8c520e20')
url = ('http://api.openweathermap.org/data/2.5/weather?q='+weathercity+'&appid=886705b4c1182eb1c69f28eb8c520e20')
def spinning_cursor():
while True:
for cursor in '|/-\\':
yield cursor
data = weather.json()
temp = data['main']['temp']
description = data['weather'][0]['description']
weatherprint ="In {}, it is currently {}°C with {}."
spinner = spinning_cursor()
for _ in range(25):
sys.stdout.write(next(spinner))
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\b')
convert = int(temp - 273.15)
print(weatherprint.format(weathercity, convert, description))
if you wanna python text spinner you can look picture
Simple:print_spinner("Hayatta en hakiki mürşit ilimdir.")
Here is the simplest loading spinner for python:
import time
spin=["loading...... ", "|", "/","-", "\"]
for i in spin:
print("\b"+i, end=" ")
time.sleep (0.2)
Output:
loading...... |

Categories