I have a python script that prints a spinner. This spinner, hopefully, will last until stopped.
spinnerFrames = [
"/",
"-",
"\\",
"|",
]
def spinner():
i = 0
while True:
clearScreen() #function to clear the screen
print(spinnerFrames[i])
i = i + 1
if (i == 3):
i = 0
sleep(0.15)
spinner()
sleep(3)
# break out here
print("Done!")
I know you can do sys.stdout.write() and then only delete that line, but that's beside the point.
I can't figure out the best way to stop the loop and exit the function. (To continue on in my code)I'd like to be able to break from the loop down where you call it, as I hope to make this a Pip package.
This, I assume is possible, though I don't know how to do it. Thanks for your help!
You need to run it asynchronously, like how the multiprocessing library allows you to do. When you create a separate thread, you'll be left with a handle on it that you can use to kill it when you want it to stop.
from multiprocessing import Process
from time import sleep
spinnerFrames = [
"/",
"-",
"\\",
"|",
]
def spinner():
i = 0
while True:
print(spinnerFrames[i], end='\r')
i = i + 1
if (i == 3):
i = 0
sleep(0.15)
if __name__ == '__main__':
p = Process(target=spinner)
p.start()
sleep(3)
p.terminate()
print("Done!")
Here is a reference implementation from one of my projects. It prints dots instead of a spinner, but it is trivial to change:
import threading
import time
def indicate_wait(func):
active = threading.Lock()
def dot_printer():
while active.locked():
print('.', end='', flush=True)
time.sleep(1)
def wrapper(*args, **kwargs):
t = threading.Thread(target=dot_printer)
active.acquire()
t.start()
res = func(*args, **kwargs)
active.release()
return res
return wrapper
Example:
#indicate_wait
def test():
time.sleep(5)
record when it started, then break loop if current time - start time >
duration.
import time
spinnerFrames = [
"/",
"-",
"\\",
"|",
]
def spinner():
i = 0
startTime = time.time()# record starting time
duration = 3
while True:
clearScreen() #function to clear the screen
print(spinnerFrames[i])
i = i + 1
if (i == 3):
i = 0
if time.time() - startTime > duration:
break
sleep(0.15)
spinner()
print("Done!")
Related
I have a script that runs but it has a tendency of hanging. I am trying to make another script to run it using threads, but the auto-restarting function does not seem to be working.
What I want this script to do is to restart the function every 900 seconds, or if it is possible, restart it whenever it hangs.
import time
import threading
import os
import functionname
def restart():
time.sleep(900)
os.execl('currentfilepath')
def res():
while True:
try:
# do your works
t = threading.Thread(target=restart, args=(), name='reset')
t.start()
functionname()
except:
print('error')
finally:
print('done')
if __name__ == '__main__':
res()
so I managed to find a way to solve this.
import multiprocessing
import time
t=600 # time to wait
def bar():
# do stuff
def barn():
for i in range(t*500): # runs for 500 times
# print ("Tick"+str(i)+'n') # just for tracking progress
time.sleep(1)
if i % t == 0:
print('restarting')
p = multiprocessing.Process(target=bar)
p.terminate
p = multiprocessing.Process(target=bar)
p.start()
if __name__ == '__main__':
p = multiprocessing.Process(target=bar)
p.start()
p1 = multiprocessing.Process(target=barn)
p1.start()
Probably not the most elegant but hey, it works.
Your answer works but it seems to be a one shot; on my system it stops running after 1 time. I changed the code to use a while loop instead; now it's working on my system:
def barn():
p = multiprocessing.Process(target=bar)
p.start()
i = 0
while(t > i):
print("running for " + str(i))
i += 1
time.sleep(1)
if i == t:
print('restarting')
p = multiprocessing.Process(target=bar)
p.terminate
p = multiprocessing.Process(target=bar)
p.start()
i = 0
I am trying to create a thread in Python that will poll some server as long as it won't get proper answer (HTTP GET). In order to provide convenient text UI I want to print progress dots. Another dot with every connection attempt until it finish (or just another dot with every another second of waiting).
I have found something like this: http://code.activestate.com/recipes/535141-console-progress-dots-using-threads-and-a-context-/
In this example we have context manager:
with Ticker("A test"):
time.sleep(10)
I am not sure if I understand that properly. I would like to do something like:
with Ticker("A test: "):
result = -1
while result != 0:
result = poll_server()
print "Finished."
But this does not work. Any ideas?
Cheers
Python buffers your output, so many dots will appear at once. One way around that is to import sys and use that: whenever you want to print a dot, say:
sys.stdout.write(".")
sys.stdout.flush()
The flush makes the dot appear immediately.
#! /usr/bin/python3
import sys
import time
def progress(message):
i = 0
while True:
dots = ""
i = (i % 3) + 1
dots += "." * i + " " * (3 - i)
sys.stdout.write("\r{}".format(message + dots))
sys.stdout.flush()
i += 1
time.sleep(0.3)
if __name__ == "__main__":
progress("Waiting")
More useful example:
#! /usr/bin/python3
import sys
import time
def progress_gen(message):
i = 0
while True:
for x in range(0, 4):
dots = "." * x
sys.stdout.write("{}\r".format(message + dots))
i += 1
time.sleep(0.5)
sys.stdout.write("\033[K")
yield
if __name__ == "__main__":
p = progress_gen("Waiting")
for x in range(1, 100):
next(p)
if x == 3:
break
print("Finished")
You can test it online: https://repl.it/#binbrayer/DotsProgress
I've made a python script that factorizes a number into its prime factors. However when dealing with big numbers i may like to have an idea to the progress of the computation. (I simplified the script)
import time, sys, threading
num = int(input("Input the number to factor: "))
factors = []
def check_progress():
but = input("Press p: ")
if but == "p":
tot = int(num**(1/2))
print("Step ", k, " of ", tot, " -- ", round(k*100/tot,5), "%", end="\r", sep="")
t = threading.Thread(target=check_progress) ?
t.daemon = True ?
t.start() ?
k = 1
while(k != int(num**(1/2))):
k = (k+1)
if num%k == 0:
factors.append(int(k))
num = num//k
k = 1
print(factors)
I'm wondering if there is a way to show the progress on demand, for example, during the loop, i press a key and it prints the progress?
How can i implement a thread of something like that in my script?
Thanks and sorry for my english
Edit:
def check_progress():
while True:
but = input("## Press return to show progress ##")
tot = int(num**(1/2))
print("Step ", k, " of ", tot, " -- ", round(k*100/tot,5), "%", sep="")
Here is one possible design:
Main thread:
create queue and thread
start the progress thread
wait user input
on input:
pop result from queue (may be None)
display it
loop
Progress thread:
do the work an put status in queue
I can provide example, but I feel you are willing to learn. Feel free to comment for help.
Edit: Full example with queue.
from time import sleep
from Queue import Queue
from threading import Thread
# Main thread:
def main():
# create queue and thread
queue = Queue()
thread = Thread(target=worker, args=(queue,))
# start the progress thread
thread.start()
# wait user input
while thread.isAlive():
raw_input('--- Press any key to show status ---')
# pop result from queue (may be None)
status = queue.get_nowait()
queue.task_done()
# display it
if status:
print 'Progress: %s%%' % status
else:
print 'No status available'
# Progress thread:
def worker(queue):
# do the work an put status in queue
# Simulate long work ...
for x in xrange(100):
# put status in queue
queue.put_nowait(x)
sleep(.5)
if __name__ == '__main__':
main()
Could anybody advise me on converting the Java Timer class to Python? Currently I am converting a Java program to a Python script. However, Python does not have the Timer/TimerTask library (if it does have this, please enlighten me. Thanks!). I need to be able to reset the Timer. Java has Timer.cancel, but Python doesn't have this. Is there any replacement for it?
timer.cancel();
timer = new Timer("Printer");
MyTask t = new MyTask();
timer.schedule(t, 0, 1000);
Java script timer
class Timerclass extends TimerTask {
//times member represent calling times.
private int times = 0;
public void run() {
times++;
if (times <= 5) {
System.out.println(""+times);
} else {
this.cancel();
//Stop Timer.
System.out.println("Timer Finish");
}
}
}
Currently my code
import time
import threading
class Variable:
count = 0
people = 0
times = 0
def enter():
if int(Variable.count == 1):
print("Entered")
t = threading.Timer(5.0, countdown)
t.start()
else:
print("Entered +1")
t.clear() // Stuck Help
t = threading.Timer(5.0, countdown)
t.start()
def out():
if int(Variable.count > 0):
print("Exited")
elif int(Variable.count < 0):
print("Error")
def countdown():
print("TIMEUP")
while True:
sensor1 = input("Sensor 1: ")
sensor2 = input("Sensor 2: ")
Variable.count+=1
if int(sensor1) == int(sensor2):
Variable.count -= 1
print(Variable.count)
print("error")
elif int(sensor1) == 1:
Variable.people += 1
print(Variable.people)
enter()
elif int(sensor2) == 1:
Variable.people -= 1
print(Variable.people)
out()
else:
print("Error")
i have one problems that i'm stuck in i need to stop the current counting and start a new one whenever the method call
Basically what i want or im looking out for is when i recall this method it will reset or cancel any existing and recount again
Update latest
import time
import threading
class Variable:
count = 0
people = 0
times = 0
def countdown():
print("TIMEUP")
t = threading.Timer(5.0, countdown)
def enter():
if int(Variable.count == 1):
print("Entered")
t.start()
else:
print("Entered +1")
t.cancel()
t.join() # here you block the main thread until the timer is completely stopped
t.start()
def out():
if int(Variable.count > 0):
print("Exited")
elif int(Variable.count < 0):
print("Error")
while True:
sensor1 = input("Sensor 1: ")
sensor2 = input("Sensor 2: ")
Variable.count+=1
if int(sensor1) == int(sensor2):
Variable.count -= 1
print(Variable.count)
print("error")
elif int(sensor1) == 1:
Variable.people += 1
print(Variable.people)
enter()
elif int(sensor2) == 1:
Variable.people -= 1
print(Variable.people)
out()
else:
print("Error")
Anybody can spot my ,istake im getting this error but i t.clear() the process
in start raise RuntimeError("threads can only be started once")
RuntimeError: threads can only be started once
I would suggest using the time module for something like this:
from time import time, sleep
from datetime import datetime, timedelta
nowtime = time()
#Put your script here
x = 1
for k in range(1000):
x+=1
sleep(0.01)
sec = timedelta(seconds=int(time()-nowtime))
d = datetime(1,1,1)+sec
print("DAYS:HOURS:MIN:SEC")
print("%d:%d:%d:%d" % (d.day-1, d.hour, d.minute, d.second))
This assigns the time in seconds at the beginning to a variable, and after the main script has finished, it subtracts the previous time from the current time and formats it in days, hours, minutes, and seconds.
Here is it running:
bash-3.2$ python timing.py
DAYS:HOURS:MIN:SEC
0:0:0:10
bash-3.2$
You could also use the Threading module, which has a built-in cancel method:
>>> import threading
>>> def hello():
... print "This will print after a desired period of time"
...
>>> timer = threading.Timer(3.0, hello)
>>> timer.start() #After 3.0 seconds, "This will print after a desired period of time" will be printed
>>> This will print after a desired period of time
>>> timer.start()
>>> timer = threading.Timer(3.0, hello)
>>> timer.start()
>>> timer.cancel()
>>>
Python actually has a class for this, which includes a cancel method: threading.Timer. It seems to be close enough to the Java Timer class for your needs (The Java Timer also runs in background thread). Here's the example usage from the docs:
def hello():
print "hello, world"
t = Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed
Edit:
The problem with your updated code is that you're trying to use the same Timer object more than once. That may be possible in the Java implementation, but in Python you can't reuse a Thread object (Timer is a Thread subclass). You'll need to create a new Timer object after you join() it. Like this:
t = threading.Timer(5.0, countdown)
def enter():
global t # You need this to tell Python that you're going to change the global t variable. If you don't do this, using 't = ..' will just create a local t variable.
if int(Variable.count == 1):
print("Entered")
t.start()
else:
print("Entered +1")
t.cancel()
t.join() # here you block the main thread until the timer is completely stopped
t = threading.Timer(5.0, countdown)
t.start()
I am currently playing with some cmd/prompt animations/graphics:
import os
import time
def printFrame(timeout, count):
os.system('cls')
l=0
while True:
for k in range(0,9):
for i in range(0,9):
for j in range(0,9):
if j == k and i != 4:
print("|", end="", flush=True)
elif j !=k and i == 4:
print("-", end="", flush=True)
elif j ==k and i == 4:
print("+", end="", flush=True)
else:
print("O", end="", flush=True)
print("")
time.sleep(timeout)
os.system('cls')
l += 1
if l > count:
break
if __name__ == "__main__":
printFrame(0.08, 2)
and i want to get rid of frame blinking - especialy visible in first line, my idea was to use second printing thread:
def printFrame(timeout, count):
#print from example1
def printFrameTwo(timeout, count):
#print from example1 without os.system('cls')
if __name__ == "__main__":
p1 = threading.Thread(target = printFrame, args = (0.08, 2))
p2 = threading.Thread(target = printFrameTwo, args = (0.08, 2))
p1.start()
p2.start()
but the effect was rather disappointing - problems with synchronization and first line still very blinky, second idea was to use 'predefined frames' - but its not very educating - the bonus here is that I can print whole line at once, but still effect is not as expected, third (most promising) idea is to only change necessary 'pixels'/chars in frame - but here I need to move in frame between lines! and curses is not working on windows (at least not in standard). Do you maybe have some ideas how to bite it? (windows, standard libraries) maybe how to speed up 'os.system('cls')'?
I figured it out... You can use ANSI codes to move the cursor then clear the lines without any BLINK!
print('\033[4A\033[2K', end='')
\033[4A Moves the cursor 4 lines up (\033[{lines}A you can replace lines with however many you need) \033[2K Clears all those lines without the screen blinking. You can use it in a simple typewrite function that needs a constant message or a box around it like this:
from time import sleep
def typewrite(text: str):
lines = text.split('\n')
for line in lines:
display = ''
for char in line:
display += char
print(f'╭─ SOME MESSAGE OR SOMEONES NAME ────────────────────────────────────────────╮')
print(f'│ {display:74} │') # :74 is the same as ' ' * 74
print(f'╰────────────────────────────────────────────────────────────────────────────╯')
sleep(0.05)
print('\033[3A\033[2K', end='')
The only problem with this is that the top line is blinking. To fix this all we need to do is to add a empty line that is blinking so the user cant see it. We also move the cursor up from 3 to 4 lines.
def typewrite(text: str):
lines = text.split('\n')
for line in lines:
display = ''
for char in line:
display += char
print('')
print(f'╭─ SOME MESSAGE OR SOMEONES NAME ────────────────────────────────────────────╮')
print(f'│ {display:74} │') # :74 is the same as ' ' * 74
print(f'╰────────────────────────────────────────────────────────────────────────────╯')
sleep(0.05)
print('\033[4A\033[2K', end='')
To make this into your code just print your text and add a print('') at the start. Then use this print('\033[4A\033[2K', end='') but change the 4 to however many lines that you printed including the print(''). Then it should work without blinking. You can put print('\033[4B', end='') at the end which just moves the cursor back up.
If you want to hide the cursor you can use this gibberish or make the cursor the same color as the background:
import ctypes
if os.name == 'nt':
class _CursorInfo(ctypes.Structure):
_fields_ = [("size", ctypes.c_int),
("visible", ctypes.c_byte)]
def hide_cursor() -> None:
if os.name == 'nt':
ci = _CursorInfo()
handle = ctypes.windll.kernel32.GetStdHandle(-11)
ctypes.windll.kernel32.GetConsoleCursorInfo(handle, ctypes.byref(ci))
ci.visible = False
ctypes.windll.kernel32.SetConsoleCursorInfo(handle, ctypes.byref(ci))
def show_cursor() -> None:
if os.name == 'nt':
ci = _CursorInfo()
handle = ctypes.windll.kernel32.GetStdHandle(-11)
ctypes.windll.kernel32.GetConsoleCursorInfo(handle, ctypes.byref(ci))
ci.visible = True
ctypes.windll.kernel32.SetConsoleCursorInfo(handle, ctypes.byref(ci))
Note: All of this is still new to me so I am still testing this out to fully understand it.