Skip to content

Commit

Permalink
Merge pull request #5 from peinan/feat/named-timefunc
Browse files Browse the repository at this point in the history
added named timer function
  • Loading branch information
peinan authored Jul 31, 2019
2 parents 9c2a57c + ef347a2 commit 262515d
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 52 deletions.
154 changes: 129 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,56 +12,160 @@

## Install

Just use pip to install.

```bash
$ pip install swpy
pip install swpy
```

## Usage

### Basic Usage

Import `Timer` class from `swpy`, and use `with` statement to capsule the block where you want timing.

```python
>>> from swpy import Timer
>>> import time
from swpy import Timer
from time import sleep

with Timer():
sleep(1)
```

Or use `start()` and `stop()` function to controll the timer.

```python
t = Timer()
t.start()
sleep(1)
t.stop()
```

# the simplest use
>>> with Timer():
... time.sleep(1)
And the output will look like below:

```
[timer-1557406243.3309178] started.
[timer-1557406243.3309178] finish time: 1.00 sec.
```

### Features

#### Name the timer

You can name the timer to make it easy to recognize.

# name the timer for visibility
>>> with Timer(name='test timer'):
... time.sleep(1)
```python
with Timer(name='test timer'):
sleep(1)
```

Now the timer is renamed to `test timer` !

```
[test timer] started.
[test timer] finish time: 1.00 sec.
```

#### Lap time and Split time

There are two types to measuring time without stoping: lap time and split time. The figure below may help you to understand the differences.

![split_lap_time](https://github.com/peinan/swpy/blob/master/imgs/split_lap_time.png)

We prepared `split` and `lap` functions for this kind of usage. The examples are below.

```python
# measure split time
with Timer('timer') as t:
sleep(1)
t.split()
sleep(1)
t.split()
sleep(1)
t.split()
```

```
# outptus
[timer] started.
[timer] split time: 1.00 sec.
[timer] split time: 2.01 sec.
[timer] split time: 3.01 sec.
[timer] finish time: 3.01 sec.
```

```python
# measure lap time
with Timer('timer') as t:
sleep(1)
t.lap()
sleep(1)
t.lap()
sleep(1)
t.lap()
```

```
# outputs
[timer] started.
[timer] lap time: 1.00 sec.
[timer] lap time: 1.01 sec.
[timer] lap time: 1.00 sec.
[timer] finish time: 3.01 sec.
```

And you can name your lap/split time in the case of measuring several tasks in a single run as below.

```python
with Timer('task timer') as t:
task1()
t.lap('task1')
task2()
t.lap('task2')
```

# use your own logger
>>> from logzero import logger
>>> import logging
>>> with Timer(name='test timer', logger=logger, level=logging.DEBUG):
... time.sleep(1)
```
# outputs
[task timer] started.
[task timer] [task1] lap time: 3.69 sec.
[task timer] [task2] lap time: 4.21 sec.
[task timer] finish time: 7.91 sec.
```

#### Use your own logger

You can use your own logger instead of the default `print`.

```python
from logzero import logger
import logging

with Timer(name='test timer', logger=logger, level=logging.DEBUG):
sleep(1)
```

It will output using logger.

```
[D 190510 14:41:59 swpy:15] [test timer] started.
[D 190510 14:42:00 swpy:15] [test timer] finish time: 1.01 sec.
```

#### Define your own callback

# process the timer result with your own function with callback
## define a slack notification function
>>> import requests, json
>>> def send_slack(msg):
... requests.post(SLACK_URL, json.dumps({'text': msg}))
Sometimes, we want to do something after the job has done like notifying the result to slack, executing the next process and so on. Callback feature will help you to do those.

## just specify the callback argument
>>> with Timer(name='experiment-1', logger=logger, level=logging.DEBUG, callback=send_slack):
... time.sleep(1)
[D 190510 14:48:17 swpy:15] [experiment-1] started.
[D 190510 14:48:18 swpy:15] [experiment-1] finish time: 1.01 sec.
```python
# define a slack notification function
import requests, json
def send_slack(msg):
requests.post(SLACK_URL, json.dumps({'text': msg}))

# just specify the callback argument
with Timer(name='experiment-1', callback=send_slack):
sleep(1)
```

## License

MIT
[MIT](https://github.com/peinan/swpy/blob/master/LICENSE)
Binary file added imgs/split_lap_time.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 13 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
[tool.poetry]
name = "swpy"
version = "0.1.1"
version = "0.1.2"
description = "A simple, yet useful stopwatch library."
authors = ["Peinan ZHANG <[email protected]>"]

license = "MIT"

authors = [
"Peinan ZHANG <[email protected]>"
]

readme = "README.md"

homepage = "https://github.com/peinan/swpy"
repository = "https://github.com/peinan/swpy"

keywords = ["stopwatch", "timer"]


[tool.poetry.dependencies]
python = "^3.6"


[tool.poetry.dev-dependencies]
pytest = "^4.0"
tox = "^3.9"
pytest-cov = "^2.7"
codecov = "^2.0"


[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"
33 changes: 19 additions & 14 deletions swpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,11 @@
[timer-1557406243.3309178] finish time: 1.00 sec.
"""

import time
import logging

import time

__author__ = 'Peinan ZHANG'
__version__ = (0, 1, 1)
__version__ = (0, 1, 2)
__license__ = 'MIT'


Expand All @@ -55,15 +54,17 @@ def __init__(self, name=None, logger=None, level=logging.DEBUG, digits=2, callba
[timer-1557406243.3309178] started.
[timer-1557406243.3309178] finish time: 1.00 sec.
"""
self.name = name if name else f'timer-{time.time()}'
self.timername = name if name else f'timer-{time.time()}'
self.print = print if not logger else lambda msg: logger.log(level, msg)
self.level = level
self.digits = digits
self.callback = callback

self.started_at = time.time()
self.times = [self.started_at]
self.print(f'[{self.name}] started.')
self.stopped_at = None
self.elapsed = None
self.print(f'[{self.timername}] started.')

def __enter__(self):
return self
Expand All @@ -74,42 +75,46 @@ def __exit__(self, exc_type, exc_value, traceback):

self.elapsed = self.stopped_at - self.started_at

msg = f'[{self.name}] finish time: {self.elapsed:.{self.digits}f} sec.'
msg = f'[{self.timername}] finish time: {self.elapsed:.{self.digits}f} sec.'
self.print(msg)

if self.callback: self.callback(msg)

def start(self, callback=None):
def start(self, title='', callback=None):
self.started_at = time.time()
self.times[0] = self.started_at

msg = f'[{self.name}] started.'
title_block = f'[{title}] ' if title else ''
msg = f'[{self.timername}] {title_block}started.'
self.print(msg)

if callback: callback(msg)

def stop(self, callback=None):
def stop(self, title='', callback=None):
self.stopped_at = time.time()
self.times.append(self.stopped_at)

self.elapsed = self.stopped_at - self.started_at

msg = f'[{self.name}] finish time: {self.elapsed:.{self.digits}f} sec.'
title_block = f'[{title}] ' if title else ''
msg = f'[{self.timername}] {title_block}finish time: {self.elapsed:.{self.digits}f} sec.'
self.print(msg)

if callback: callback(msg)
elif self.callback: self.callback(msg)

def split(self, callback=None):
def split(self, title='', callback=None):
self.times.append(time.time())
msg = f'[{self.name}] split time: {self.times[-1] - self.times[0]:.{self.digits}f} sec.'
title_block = f'[{title}] ' if title else ''
msg = f'[{self.timername}] {title_block}split time: {self.times[-1] - self.times[0]:.{self.digits}f} sec.'
self.print(msg)

if callback: callback(msg)

def lap(self, callback=None):
def lap(self, title='', callback=None):
self.times.append(time.time())
msg = f'[{self.name}] lap time: {self.times[-1] - self.times[-2]:.{self.digits}f} sec.'
title_block = f'[{title}] ' if title else ''
msg = f'[{self.timername}] {title_block}lap time: {self.times[-1] - self.times[-2]:.{self.digits}f} sec.'
self.print(msg)

if callback: callback(msg)
Expand Down
Loading

0 comments on commit 262515d

Please sign in to comment.