I have an assignment where I need to create a stopwatch, but only for IDLE. Here's what I have so far, I'm not sure how to convert the times to normal time.
import time
start = 0
def stopwatch():
while True:
command = input("Type: start, stop, reset, or quit: \n")
if (command == "quit"):
break
elif (command == "start"):
start = time.time()
print(start)
stopwatch2()
elif (command == "stop"):
stopwatch()
elif (command == "reset'"):
stopwatch()
else :
break
def stopwatch2():
while True:
command = input("Type: stop, reset, or quit: \n")
if (command == "quit"):
break
elif (command == "stop"):
total = time.time() - start
print(total)
stopwatch()
elif (command == "reset'"):
stopwatch()
else:
break
stopwatch()
Thanks for your help!
You can use datetime.timedelta():
import datetime
print(datetime.timedelta(seconds=total))
For example:
In [10]: print datetime.timedelta(seconds=10000000)
115 days, 17:46:40
Think of it like this... Idle is really no different than coding in the interactive python interpreter which I do all the time (well, I use ipython).
Think of your stopwatch like an object. What functionality does it have? Things like start, stop, reset.
This may not be the most efficient way to solve the problem but here is what I would do.
>>> import time
>>> class StopwatchException:
pass
>>> class IsRunningException(StopwatchException):
pass
>>> class NotRunningException(StopwatchException):
pass
>>> class Stopwatch():
def __init__(self):
self._times = []
self._is_running = False
def start(self):
if self._is_running:
raise IsRunningException
self._is_running = True
tracker = {
'start': time.time(),
'stop': None,
}
self._times.append(tracker)
def stop(self):
if not self._is_running:
raise NotRunningException
tracker = self._times[-1]
# the dict is mutable, and tracker is a shallow copy
tracker['stop'] = time.time()
#print(self._times[-1])
self._is_running = False
def reset(self):
if self._is_running:
raise IsRunningException
self._times = []
def total(self):
if self._is_running:
raise IsRunningException
total = 0.0
for t in self._times:
total += t['stop'] - t['start']
return total
>>> s = Stopwatch()
>>> s.start()
>>> s.stop()
>>> s.total()
6.499619960784912
>>> s.reset()
>>> s.total()
0.0
To me, anytime you want to model a real world object or "thing", OOP makes the most sense. Heres a simple argument for each element of the program:
Classes
StopwatchException
Base exception class for the stopwatch class.
IsRunningException
Raised if the stopwatch is running when it should be stopped.
NotRunningException
Raised if the stopwatch is not running when it should be.
Stopwatch
This represents the actual stopwatch.
Stopwatch Class
init
A basic stopwatch class really only needs to instance variables. A variable that stores each start/stop time (allows them to be computed later) and a variable that stores the "state" of the stopwatch (on/off or running/stopped).
start
First we need to make sure the stopwatch isn't already running.
Then we need to set it's state to running and store the time in self._times.
I chose to use a local variable and store each time pair as a dictionary with the keys 'start' and 'stop'. I chose a dictionary because it is mutable. You could also have a list with index 0 being the start time and index 1 being the stop time. You cannot use a tuple for this since tuples are immutable.
Also, the "temporary" variable is not necessary but I used it for readability.
stop
First we need to make sure the stopwatch is actually running.
Then we set the state as 'stopped' (using our boolean self._is_running) and store our stop time, similar to what we did with start. I think it doesn't matter whether you set the boolean at the beginning or the end, although I chose to set it at the beginning of the start function and the end of the stop function so that the times would not include the time needed to update a boolean variable (even though it's a trivial task, it could be much more complex in more complex programs).
reset
Make sure the stopwatch isn't running
Set self._times to be an empty list.
total
Make sure the stopwatch isn't running.
Optional: You can stop the stopwatch here if it's running, but I prefer to raise an exception.
Iterate through each list item in self._times and calculate the difference between stop and start.
Related
I'm self-learning python so I don't know how to describe this in a way that would be clear, so here's the easiest by proxy example I can come up with in pseudo code:
#where r() is a random number function
objCount = 0
def mainfunc()
while playgame= True and objCount < 100:
create(r(time))
time.sleep(1)
return None
def create(tmptime)
global objCount
objCount = objCount+1
newobj = plotSomething(r(x),r(y))
time.sleep(tmptime)
selfDelete..
return None
mainfunc() #run it
Instead of it making a random "lived" object every second, it makes a random lived object every second, but waits for it's "life" to expire. I'm trying to just fire this thing off to a sidechain to timeout on its own while still making new things.
All the documentation is getting super involved using asyncio, multithreading, etc.
Is there an easy way to kick this thing out of the main loop and not hold up traffic?
laziest method for simplicity is :
import concurrent.futures as delayobj
#where r() is a random number function
objCount = 0
def mainfunc()
global objCount
with delayobj:
while objCount < 100:
delayobj.ThreapoolExecutor().submit(create,tmptime=r(time))
time.sleep(1)
return None
def create(tmptime)
global objCount
objCount = objCount+1
newobj = plotSomething(r(x),r(y))
time.sleep(tmptime)
selfDelete..
return None
mainfunc() #run it
thanks again guys
I'm writing a text-based RPG for a class, and am stuck on a code predicament...
from tkinter import *
...
runOnce = False
nextRun = False
"""Main Loop"""
while True:
#New Game initialize
if you.rName == None and runOnce == False:
log("What is your name, adventurer?", eventLog)
runOnce = True
if you.rName != None and nextRun == False:
log(f'What is your profession, {you.rName}?', eventLog)
nextRun = True
#keypresses
playerInput.bind("<Return>", keyPress)
playerInput.bind("<FocusIn>", focusIn)
top.update()
top.update_idletasks()
What I have currently works, but there are a ton more if-statement type situations that need responses before continuing to the next statement. The loop is to continuously update the GUI as the game is run.
How can I code the something that needs a response once within a while loop efficiently?
Seeing the clarification, I agree with the comments these type of actions shouldn't belong in the loop. These should be all data that are collected prior to the main game loop.
If you're looping through these to validate for inputs, you can have separate loops instead:
while not you.name:
you.name = input('Enter name: ')
# some additional validation text if necessary...
while not you.job:
you.job = input('Enter job: ')
# some additional validation text if necessary...
while True:
# main game loop requiring you.name, you.job
Another approach is a bit contrived. You can pre-define these functions before your mainloop and create a RunOnce class to only execute these functions once:
class RunOnce(object):
def __init__(self, func):
self.func = func
self.ran = False
def __call__(self):
if not self.ran:
self.func()
self.ran = True
# once the function has been called,
# flip self.ran so it won't fire again.
# Decorate your functions with this special class
#RunOnce
def get_name():
you.name = input('Enter Name: ')
#RunOnce
def get_job():
you.job = input('Enter Job: ')
And then when you are in the main game loop:
while True:
get_name() # this will run once
get_job() # this too will run once
get_name() # this won't run anymore
get_job() # this neither.
The benefit of this approach is it gives you the flexibility to re-run the function if necessary:
get_name() # get_name.ran becomes True
get_name.ran = False # reset the flag
get_name() # this will run again.
I'd still say it's much better to just restructure your code so that things that only need to be captured once stay outside the main loop.
Try checking your parameters for null before using them. If you're looking for user input you can do this:
userInput = None
while True:
userInput = input("Do the thing only once") if userInput is None else userInput
...
I have a problem with functions. I want to know is it possible to when calling function second time program jump to that line of code, just like in assembler where would I use jmp directive. So when I firstly call decision_function after that some calc_funcs are done ( it doesn't matter what they do ), but when I call that same decision function second time I don't get execution of calc funcs.
def main():
decision_function()
calc_function1()
calc_function2()
calc_function3()
decision_function(reqierment)
def decision_function(reqierment=None):
if reqierment is None:
do this
else:
do that
I prefer using setting a variable to true:
skipper = true
def main():
decision_function()
calc_function1()
calc_function2()
calc_function3()
decision_function(reqierment)
def decision_function():
if skipper == True:
do this
skipper = False
else:
do that
I have this class called DecayingSet which is a deque with expiration
class DecayingSet:
def __init__(self, timeout): # timeout in seconds
from collections import deque
self.timeout = timeout
self.d = deque()
self.present = set()
def add(self, thing):
# Return True if `thing` not already in set,
# else return False.
result = thing not in self.present
if result:
self.present.add(thing)
self.d.append((time(), thing))
self.clean()
return result
def clean(self):
# forget stuff added >= `timeout` seconds ago
now = time()
d = self.d
while d and now - d[0][0] >= self.timeout:
_, thing = d.popleft()
self.present.remove(thing)
I'm trying to use it inside a running script, that connects to a streaming api.
The streaming api is returning urls that I am trying to put inside the deque to limit them from entering the next step of the program.
class CustomStreamListener(tweepy.StreamListener):
def on_status(self, status, include_entities=True):
longUrl = status.entities['urls'][0]['expanded_url']
limit = DecayingSet(86400)
l = limit.add(longUrl)
print l
if l == False:
pass
else:
r = requests.get("http://api.some.url/show?url=%s"% longUrl)
When i use this class in an interpreter, everything is good.
But when the script is running, and I repeatedly send in the same url, l returns True every time indicating that the url is not inside the set, when is supposed to be. What gives?
Copying my comment ;-) I think the indentation is screwed up, but it looks like you're creating a brand new limit object every time on_status() is called. Then of course it would always return True: you'd always be starting with an empty limit.
Regardless, change this:
l = limit.add(longUrl)
print l
if l == False:
pass
else:
r = requests.get("http://api.some.url/show?url=%s"% longUrl)
to this:
if limit.add(longUrl):
r = requests.get("http://api.some.url/show?url=%s"% longUrl)
Much easier to follow. It's usually the case that when you're comparing something to a literal True or False, the code can be made more readable.
Edit
i just saw in the interpreter the var assignment is the culprit.
How would I use the same obj?
You could, for example, create the limit object at the module level. Cut and paste ;-)
It seems that this question is too long for anyone to comment on... I'm trying to print out some text and a progress bar in a module called 'laulau.py'. Here's a test piece of code that shows a simple version. My goal is to have only one thread, and send information to it. My question is what is the best way to do this ?
file1 (test.py)
#!/usr/bin/env python
from laulau import laulau
import time
print "FIRST WAY"
total=107
t=laulau()
t.echo('this is text')
t.setbartotal(total)
for a in range(1,total):
t.updatebar(a)
time.sleep(0.01)
time.sleep(1)
print
print "\ndone loop\n"
t.stop()
time.sleep(1)
print "SECOND WAY"
with laulau().echo("this is text"):
time.sleep(1)
print "\nyes this is working\n"
time.sleep(2)
file2: laulau.py
#!/usr/bin/env python
# vim:fileencoding=utf8
from __future__ import division
import time
import string
import threading
from sys import stdout
class laulau(threading.Thread):
def __init__(self, arg=None):
super(laulau,self).__init__()
self._stop = False
self.block='█'
self.empty='□'
self.TEMPLATE = ('%(progress)s%(empty)s %(percent)3s%%')
self.progress = None
self.percent = 0
self.bar_width=30
self.bartotal=None
def run (self):
# start thread for text
while not self._stop:
if self.bartotal is None:
print self.arg,
stdout.flush()
time.sleep(0.3)
else:
self.progress = int((self.bar_width * self.percent) / 100)
self.data = self.TEMPLATE % {
'percent': self.percent,
'progress': self.block * self.progress,
'empty': self.empty * (self.bar_width - self.progress),
}
stdout.write('\033[%dG'%1 + self.data + self.arg)
stdout.flush()
time.sleep(0.1)
def setbartotal(self,total):
# set progress bar total
if self.bartotal is None:
self.bartotal = total
self.updatebar(0)
def updatebar (self,num):
self.num=num
self.percent = self.percentage(self.num)
def percentage (self,numagain):
return int((numagain/self.bartotal)*100+1)
def echo (self,arg="Default"):
#self.thread_debug()
self.arg=arg
self._stop = False
self.start()
return self
def thread_debug(self):
print "threading enumerate :%s"%threading.enumerate()
print "current thread :%s"%threading.currentThread()
print "thread count (including main thread):%s"%threading.activeCount()
def stop(self):
self._stop = True
def stopped(self):
return self._stop == True
def __enter__(self):
print "\nwe have come through the enter function\n"
return self
def __exit__(self, type, value, traceback):
self._stop = True
print "\nwe have exited through the exit function\n"
return isinstance(value, TypeError)
In some cases the second way could work. e.g., when I am printing some text, and just need the thread to die at the end of it, but not in the case of a progress bar when it needs updates sending to it. While this all sort of works, and I learned a lot, I still can't figure out how to encapsulate this class in the way I want. As I only want one thread I don't really need to keep instantiating the class, I just need to do this once.
so e.g. my ideal way would be having three functions only:
1 to control text, turn on progress bar etc (from within one parsed string)
2 to set the progress bar total
3 to set the progress bar iteration
I need to change two variables in the class (for the progress bar)
one for the total
one for the iteration
...and it works out percentage from that.
First I thought I should start the thread by inheriting the class stuff from threading, then after looking at threading.Thread(target=blah,etc) at first I couldn't see how to use more than one function, then I discovered I could just put the class name in there threading.Thread(target=laulau) and that would start a thread with the class in, but then I was stumped on how to send that thread information seeing as I hadn't assigned it to a 'name' as in t=laulau()
My second thought was to have functions outside of the class in my module, but because I need more than one function I got a bit confused there too by adding this to the beginning of laulau.py:
def eko (arg):
t=laulau()
t.echo(arg)
def barupate(iteration):
t.updatebar(a)
def bartotal():
t.setbartotal(a)
the first function made an instance of the class but the preceding functions could not change any variables within that. and then i came across function attributes such as this.
class Foo:
#webmethod
def bar(self, arg1, arg2):
...
def webmethod(func):
func.is_webmethod = True
return func
I then started thinking maybe I could use this somehow but have never come across it before.
Ideally id like something like this:
echo.total(107)
echo('[progressbar] this is text') # starts progress bar and instance of thread if not already there...
for a in range(1,total):
echo.updatebar(a)
time.sleep(0.01)
time.sleep(1)
echo.stop() # bar would stop at the end of iterations but text animations (blinking etc) may still be going at this point...
print
print "\ndone loop\n"
if you know about python you are probably looking at me funny now, but bear in mind that I'm a total beginner non-professional and am learning every day, a lot of it thanks to this site. cheers for any help!
edit: should add that I'm aware of the progress bar module and various other recipes, but I'm making this for learning and fun purposes :)
If you just need to print out a progress bar, use the sys module, like so:
import sys
import time
progress = "0" #this is an int meant to represent 0-100 percent as 0-100
old = "0" #this represents the last updates progress, so that this update only adds the difference and not the full progress
def updatebar(progress,old):
for item in range((progress-old)/2) #this takes the range of progress but divides it by 2, making the progress bar 50 characters long
sys.stdout.write("-") #to change the character used to fill the progress bar change the "-" to something else
sys.stdout.flush()
#you may not want to use a while loop here, this just has an example of how to use the update function as it adds one to the progress bar every second
while True:
progress += 1
updatebar(progress,old)
old = progress #sets the old progress as the current one, because next iteration of the while loop the previous progress will be this one's current progress.
time.sleep(1)