Time

This module contains classes that handle time : either measure it, wait or even control it !

Timer

Timer pause your script for the given number of seconds. With quite the same design as wheel, you may add a message next to the timer.

from pyux.time import Timer

# A timer for 3 seconds with a message
Timer(delay = 3, message = 'Pausing 3 secs, tired')

# A timer with no message
Timer(delay = 3)

The timer can also be used as an iterable’s decoration within a for statement, when you repeatedly have to await the same delay at each iteration. Specifying overwrite = True allows each iteration to be rewritten on the same line, which is advised when used in that case.

Note that the first argument to Timer is iterable and not delay, and all of them have default values, so Timer(5) won’t have the expected behaviour !

By default, a timer in a for loop prints the iteration index next to the timer. Use pattern argument to specify a prefix to add to the default iteration index (default to ''), or print_value to print the iteration value rather than the index.

from pyux.time import Timer

for fruit in Timer(['banana', 'apple', 'tomato'], delay = 3, print_value = True):
   pass

Again, the Timer.close() makes the counter go to zero included and flushes a new line. It is called automatically when used as a loop decoration.

Wait

Use wait to decorate a function that you want to pause for a given amount of time before or after each execution. It can be useful for API calls in loops where you have await a certain time between each API call. The pause can be made before or after the function call, and Timer can be used instead of the built-in sleep function with timer = True.

from pyux.time import wait

@wait(delay = 3, before = True)
def do_nothing():
   return
do_nothing()

timeout

timeout decorates a function that you want to timeout after a given delay.

from pyux.time import timeout

@timeout(delay = 5)
def unstopable_function():
   i = 0
   while i >= 0:
      i += 1
   return i

unstopable_function()    # timeout stops execution after 5 seconds

Chronos

Use Chronos to measure user execution time, for a script or a loop. It works as a stopwatch : rather than wrapping around and timing an expression, it triggers at start, then the method Chronos.lap() records time with timeit.default_timer() each time it is called (thus resembling a lap button on a stopwatch).

from time import sleep
from pyux.time import Chronos

chrono = Chronos()
print('Step one with duration approx. 1.512 secs')
sleep(1.512)
chrono.lap(name = 'step 1')

print('Step two with duration approx. 1.834 secs')
sleep(1.834)
chrono.lap(name = 'step 2')

chrono.compute_durations(ms = True)

print('\nNow printing durations :')
for name, time in chrono.durations.items():
    print('Time for step %s : %d ms' % (name, time))

Durations can be written in a tsv file with Chronos.write_tsv(). The method uses an append mode, so you can append times from different runs to the same tracking file, for instance. Argument run_name in that method allows you to give a name to a run especially for that purpose (the name appears as the first column of the written file).

Three columns are written, with default names Execution (the one presented just above), Step and Duration (secs). These names can be changed with argument col_names.

If you want to time iterations in a for loop, you can use it as a decoration for the iterable. Since you won’t be able to assign the object back when the loop finishes, you can choose to print durations in console, or write them into a tsv file.

from pyux.time import Chronos
from pyux.time import Timer

for index, value in enumerate(Chronos(range(1, 4), console_print = True, ms = True)):
   Timer(delay = value, message = 'At iteration %d' % index, overwrite = True)

Depending on the number of arguments you provide, declaration in the for statement can become rather verbose. Feel free to initiate the chrono outside of the loop, in which case, the object remains available after the loop (if you need to add steps from the rest of the code afterwards, for instance).

from pyux.time import Chronos
from time import sleep
from os import unlink

timed_iterable = Chronos(
   iterable = range(25),
   console_print = True,
   write_tsv = True,
   run_name = 'verbose_declaration',
   path = 'example_times.tsv',
   col_names = ('run', 'lap', 'duration (msecs)'),
   ms = True
)
for value in timed_iterable:
    sleep(value / 1000)
# unlink('example_times.tsv')

Detailed documentation

class pyux.time.Chronos(iterable=None, console_print: bool = False, pattern: str = 'iteration ', write_tsv: bool = False, run_name: str = 'default', path: str = None, col_names=None, ms: bool = False)

Bases: object

Time chunks of code in a script.

The class works as a stopwatch during a race on track : after starting it, for each lap, a button is pushed that records time at this moment, using timeit.default_timer().

Parameters:
  • iterable (iterable or int) – default None : for decorator use only : an iterable, or an integer for standard range(n) values.
  • ms (bool) – default False : compute durations in milliseconds
  • console_print (bool) – default False : for decorator use only : print durations in tsv format in console when loop is finished
  • pattern (str) – default 'iteration ' : for decorator use only : pattern for naming laps, will be suffixed with the iteration number
  • write_tsv (bool) – default False : for decorator use only : write out tsv file end loop is finished
  • run_name (str) – default 'default' : for decorator use only : name to give to execution for column Execution
  • path (str) – default None : for decorator use only : full path to file to write
  • col_names (tuple) – default None : for decorator use only : column names (length 3)

Recorded times do not have a meaning by themselves since they do not correspond to durations and depends on the previous recorded times. When you want to know duration of recorded laps, use compute_durations(), which gives durations for each lap and total duration.

Chronos can be used as a decorator in a for loop. In that case, it records duration for each iteration. Since you cannot get the object back, you can either print the values to console (in tsv format) or write out the values in a tsv file.

Specifying an iterable argument while calling Chronos() outside of a for statement has no effect. In that case, you can still use it manually, as if you entered nothing for that argument.

Results can be exported in a tsv file with write_tsv().

Example:
>>> from time import sleep
>>> chrono = Chronos()
>>> sleep(2)
>>> chrono.lap(name = 'lap 1')
>>> sleep(5)
>>> chrono.lap(name = 'lap 2')
>>> chrono.compute_durations().durations
>>> # In a for loop
>>> for index in Chronos(10, console_print = True, write_tsv = False):
>>>     pass
compute_durations(ms: bool = False)

Compute laps durations.

Duration is the difference between two adjacent laps. Results are stored in self.durations, in seconds by default. They can be stored in milliseconds. The total duration is also calculated.

Parameters:ms (bool) – express durations in milliseconds rather than seconds
Returns:self
lap(name: str)

Record time for this lap; a name must be provided.

write_tsv(run_name: str, path: str, col_names: tuple = None)

Export durations in a tsv file.

Write three columns, the first containing run_name : a string describing which execution the durations came from. This way you can append several execution times to the same file.

Default values for column names are : Execution, Step, Duration (secs)

Parameters:
  • run_name (str) – name to give to execution for column Execution
  • path (str) – full path to file to write
  • col_names (tuple) – default None : column names of length 3
Returns:

self

class pyux.time.Timer(iterable=None, delay: int = None, message: str = '', ms: bool = False, pattern: str = '', print_value: bool = False, overwrite: bool = False)

Bases: object

Print a descending timer for a given delay.

A message can be printed next to the timer. The class can be used on the iterable of a for loop to wait the same amount of time at each iteration.

Parameters:
  • iterable (iterable or int) – default None : for decorator use only : an iterable, or an integer for standard range(n) values
  • delay (int) – default None : time to wait, must be provided. Default to seconds, can be milliseconds with ms = True
  • message (str) – default '' : message to print when used manually
  • ms (bool) – default False : use a delay in milliseconds
  • pattern (str) – default '' : for decorator use only : prefix to print before iterated value when used as a loop decorator and print_value = False
  • print_value (bool) – default False : for decorator use only : Print running value of the iterable when used to decorate a loop instead of iteration index
  • overwrite (bool) – default False : do not print a new line when the timer is finished (useful almost only when used within a loop)

When used within a for loop, the default behavior is to print the iteration index next to the timer. You can add a constant string prefix to it using the argument pattern (which is not used otherwise), or use print_value = True to print the running value of the iterable.

Specifying a value for iterable while calling Timer() outside of a for statement will have no effect (except if you use the result in a for statement afterwards, obviously).

Raises:DelayTypeError if no or wrong type delay is given
Example:
>>> # One-shot usage
>>> Timer(delay = 10, message = "Waiting for 10 seconds")
>>> # Usage as a decorator
>>> for index in Timer(3, delay = 3):
>>>     pass
close(message: str, overwrite: bool) → None

Print '0' when time has passed (last iteration is 1).

static print(time: str, message: str) → None

Print the counter for a given time, counter and message.

pyux.time.timeout(delay: float)

Stop a function if running time exceeds delay (seconds).

To be used as a decorator.

Parameters:delay (float) – time in seconds before stopping running function
Example:
>>> @timeout(delay = 10)
>>> def infinite_fun():
>>>     while True:
>>>         pass
pyux.time.wait(delay: float, before: bool = True, timer: bool = False, **timer_args)

Wait a given delay before or after a function call.

The function is used as a target function’s decoration. With default values nothing is printed during pause, but a Timer can be printed instead.

Parameters:
  • delay (float) – time to wait (in seconds)
  • before (bool) – default True : pause before function execution
  • timer (bool) – default False : print a timer during pause
  • timer_args (see Timer) – keyword arguments for Timer when timer = True
Returns:

a function decorated with a timer

Example:
>>> @wait(delay = 3)
>>> def print_hello():
>>>     print('hello')
>>> print_hello()