Package: la-stopwatch
la-stopwatchMeasure the amount of time that elapses betweenlap times.installpip install la-stopwatchusageThere are two versions of stopwatch:StopwatchNSStopwatchWhile both measure using nanoseconds, the second option convert nanoseconds totimedeltabefore returning any time measurement. All examples will be usingStopwatchbecausetimedeltait's easy to read, but it doesn't matter each you use because both have the same methods.basicThe first thing you should know is that time start whenStopwatchis created.fromtimeimportsleepfromla_stopwatchimportStopwatchstopwatch=Stopwatch()time.sleep(1)print(stopwatch.duration())# 0:00:01.001374Retrive the current time withduration().recordYou can record eachlap timefor future analysis usingrecord().stopwatch=Stopwatch()time.sleep(1)stopwatch.record()time.sleep(1)stopwatch.record()print(stopwatch.get_record(0))# 0:00:01.001317print(stopwatch.get_record(1))# 0:00:02.002678Useget_record(n)to get the nº record.named recordIs possible to give a name for each record.stopwatch=Stopwatch()time.sleep(1)stopwatch.record("first")time.sleep(1)stopwatch.record("second")time.sleep(1)stopwatch.record("third")print(stopwatch.get_record("first"))# 0:00:01.001374print(stopwatch.get_record("second"))# 0:00:02.002231print(stopwatch.get_record("third"))# 0:00:03.003551all recordsAll records (nameless or not) are available withget_records().stopwatch=Stopwatch()time.sleep(1)stopwatch.record()time.sleep(1)stopwatch.record("second")time.sleep(1)stopwatch.record()# {#   0: datetime.timedelta(seconds=1, microseconds=392),#   'second': datetime.timedelta(seconds=2, microseconds=1447),#   1: datetime.timedelta(seconds=3, microseconds=2614)# }print(stopwatch.get_records())chain callsSome methods return theStopwatchso you can chain method calls. For example, you can record how much time take to do each action if you reset every time after recording.stopwatch=Stopwatch()time.sleep(1)stopwatch.record().reset()time.sleep(1)stopwatch.record()print(stopwatch.get_record(0))# 0:00:01.001267print(stopwatch.get_record(1))# 0:00:01.000460context managerStopwatchaccepts a callback as argument which will be called on exit of context managers receving the duration.# 0:00:01.001578withStopwatch(print):time.sleep(1)The advantage of context manager is that you can interact withStopwatchduring the scope.# 0:00:00.000082withStopwatch(print)asstopwatch:time.sleep(1)stopwatch.reset()The callback receive any extra arguments duringStopwatchinitialization and the duration. Duration will be passed insidekwargswith the name durationoras last argument (in casekwargsis empty).defon_finish(msg,duration):print(msg,duration)# Success 0:00:01.001218withStopwatch(on_finish,"Success"):time.sleep(1)It's okay to use inside a class withselfkeyword.classTest():defon_finish(self,msg,grade,duration):print(msg,grade,duration)defstart(self):withStopwatch(self.on_finish,"Success",grade="A+"):time.sleep(1)# Success A+ 0:00:01.001470Test().start()decoratorStopwatchaccepts a callback as argument which will be called on exiting decoratored functions.@Stopwatch(print)defmain():time.sleep(1)# 0:00:01.001281main()The callback needs to be identical to the decorated function but with the last argument being duration. Duration will be passed insidekwargswith the name durationoras last argument (in casekwargsis empty).defon_finish(student,msg,duration,grade):print(student,msg,duration,grade)@Stopwatch(on_finish)defmain(student,msg="Success",grade="A+"):time.sleep(1)# Bob Success 0:00:01.000698 A+main("Bob")It's okay to use inside a class withselfkeyword.classTest():defon_finish(self,student,msg,duration,grade):print(student,msg,duration,grade)@Stopwatch(on_finish)defstart(self,student,msg="Success",grade="A+"):time.sleep(1)# Bob Success 0:00:01.000500 A+Test().start("Bob")asyncWhileStopwatchalone doesn't have reason to use asynchronous code, it can fit your asynchronous code easly. You may need this when:Decorating anasyncfunctionThe Callback is anasyncfunctionasync - context managerWhenever you are inside an asynchronous function useasync with.importasynciofromla_stopwatchimportStopwatchasyncdefon_finish_1(duration):print(duration)defon_finish_2(duration):print(duration)asyncdefmain():asyncwithStopwatch(on_finish_1):awaitasyncio.sleep(1)asyncwithStopwatch(on_finish_2):awaitasyncio.sleep(1)# 0:00:01.001196# 0:00:01.001875asyncio.run(main())It will check whenever you callback is asynchronous or not before calling, so you can change the callback as you feel like without breaking your code.async - decoratorSame as context managers, it will check whenever your callback is asynchronous or not before calling.asyncdefon_finish(duration):print(duration)@Stopwatch(on_finish)asyncdefmain():awaitasyncio.sleep(1)# 0:00:01.002338asyncio.run(main())importasynciofromla_stopwatchimportStopwatchdefon_finish(duration):print(duration)@Stopwatch(on_finish)asyncdefmain():awaitasyncio.sleep(1)# 0:00:01.002063asyncio.run(main())