Package: timebudget
timebudgetA stupidly-simple tool to see where your time is going in Python programsTrying to figure out where the time's going in your python code?  Tired of writingelapsed = time.time() - start_time?  You can find out with just a few lines of code after youpip install timebudgetThe simplest wayWith just two lines of code (one is the import), you can see how long something takes...fromtimebudgetimporttimebudgetwithtimebudget("Loading and processing the file"):raw=open(filename,'rt').readlines()lines=[line.rstrip()forlineinraw]will printLoading and processing the file took 1.453secRecord times and print a reportTo get a report on the total time from functions you care about, just annotate those functions:fromtimebudgetimporttimebudgettimebudget.set_quiet()# don't show measurements as they happentimebudget.report_at_exit()# Generate report when the program exits@timebudget# Record how long this function takesdefpossibly_slow():...@timebudget# ... and this function toodefshould_be_fast():...And now when you run your program, you'll see how much time was spent in each annotated function:timebudget report...
            possibly_slow:  901.12ms for      3 calls
           should_be_fast:   61.35ms for      2 callsOr instead of callingreport_at_exit()you can manually calltimebudget.report(reset=True)# print out the report now, and reset the statisticsIf you don't setreset=Truethen the statistics will accumulate into the next report.You can also wrap specific blocks of code to be recorded in the report, and optionally override
the defaultset_quietchoice for any block:withtimebudget("load-file",quiet=False):text=open(filename,'rt').readlines()Percent of time in a loopIf you are doing something repeatedly, and want to know the percent of time doing different things, time the loop itself, and pass the name to report.  That is, add a timebudget annotation or wrapper onto the thing which is happening repeatedly.  Each time this method or code-block is entered will now be considered one "cycle" and your report will tell you what fraction of time things take within this cycle.@timebudgetdefouter_loop():ifsometimes():possibly_slow()should_be_fast()should_be_fast()for_inrange(NUM_CYCLES):outer_loop()timebudget.report('outer_loop')Then the report looks like:timebudget report per outer_loop cycle...
               outer_loop: 100.0%   440.79ms/cyc @     1.0 calls/cyc
            possibly_slow:  40.9%   180.31ms/cyc @     0.6 calls/cyc
           should_be_fast:  13.7%    60.19ms/cyc @     2.0 calls/cycHere, the times in milliseconds are the totals (averages per cycle), not the average time per call.  So in the above example,should_be_fastis taking about 30ms per call, but being called twice per loop.  Similarly,possibly_slowis still about 300ms each time it's called, but it's only getting called on 60% of the cycles on average, so on average it's using 41% of the time inouter_loopor 180ms.RequirementsNeeds Python 3.6 or higher.  Other libraries are inrequirements.txtand can be installed likepip install -r requirements.txt  # only needed for developing timebudget.TestingTo run tests:pytestInspirationThis tool is inspired byTQDM, the awesome progress bar.  TQDM is stupidly simple to add to your code, and just makes it better.  I aspire to imitate that.