giving


Namegiving JSON
Version 0.4.2 PyPI version JSON
download
home_pagehttps://github.com/breuleux/giving
SummaryReactive logging
upload_time2023-03-24 19:32:15
maintainer
docs_urlNone
authorOlivier Breuleux
requires_python>=3.7,<4.0
licenseMIT
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            
# giving — the reactive logger

[Documentation](https://giving.readthedocs.io)

`giving` is a simple, magical library that lets you log or "give" arbitrary data throughout a program and then process it as an event stream. You can use it to log to the terminal, to [wandb](https://wandb.ai/site) or [mlflow](https://mlflow.org/), to compute minimums, maximums, rolling means, etc., separate from your program's core logic.

1. Inside your code, **`give()`** every object or datum that you may want to log or compute metrics about.
2. Wrap your main loop with **`given()`** and define pipelines to map, filter and reduce the data you gave.


## Examples


<table>
<tr>
<th>Code</th>
<th>Output</th>
</tr>

<!-- ROW -->

<tr>
<td>

Simple logging

```python
# All calls to give() will log to the configured console
with given().display():
    a, b = 10, 20
    # Without parameters: last expression + result
    give()
    # With parameters:
    # parameter is just value: value => value
    # parameter is key and value: key => value
    give(a * b, c=30)
```

</td>
<td>

```
a: 10; b: 20
a * b: 200; c: 30
```

</td>
</tr>
<tr></tr>

<!-- ROW -->

<tr>
<td>

Extract values into a list

```python
# give(key=value) with key == "s" will add value to `results`
with given()["s"].values() as results:
    s = 0
    for i in range(5):
        s += i
        give(s)

print(results)
```

</td>
<td>

```
[0, 1, 3, 6, 10]
```

</td>
</tr>
<tr></tr>

<!-- ROW -->

<tr>
<td>

Reductions (min, max, count, etc.)

```python
def collatz(n):
    while n != 1:
        give(n)
        n = (3 * n + 1) if n % 2 else (n // 2)

with given() as gv:
    gv["n"].max().print("max: {}")
    gv["n"].count().print("steps: {}")

    collatz(2021)
```

</td>
<td>

```
max: 6064
steps: 63
```

</td>
</tr>
<tr></tr>

<!-- ROW -->

<tr>
<td>

Using the `eval` method instead of `with`:

```python
st, = given()["n"].count().eval(collatz, 2021)
print(st)
```

</td>
<td>

```
63
```

</td>
</tr>
<tr></tr>

<!-- ROW -->

<tr>
<td>

The `kscan` method

```python
with given() as gv:
    gv.kscan().display()

    give(elk=1)
    give(rabbit=2)
    give(elk=3, wolf=4)
```

</td>
<td>

```
elk: 1
elk: 1; rabbit: 2
elk: 3; rabbit: 2; wolf: 4
```

</td>
</tr>
<tr></tr>

<!-- ROW -->

<tr>
<td>

The `throttle` method

```python
with given() as gv:
    gv.throttle(1).display()

    for i in range(50):
        give(i)
        time.sleep(0.1)
```

</td>
<td>

```
i: 0
i: 10
i: 20
i: 30
i: 40
```

</td>
</tr>
<tr></tr>

</table>

The above examples only show a small number of [all the available operators](https://giving.readthedocs.io/en/latest/ref-operators.html).


## Give

There are multiple ways you can use `give`. `give` returns None *unless* it is given a single positional argument, in which case it returns the value of that argument.

* **give(key=value)**

  This is the most straightforward way to use `give`: you write out both the key and the value associated.

  *Returns:* None

* **x = give(value)**

  When no key is given, but the result of `give` is assigned to a variable, the key is the name of that variable. In other words, the above is equivalent to `give(x=value)`.

  *Returns:* The value

* **give(x)**

  When no key is given and the result is *not* assigned to a variable, `give(x)` is equivalent to `give(x=x)`. If the argument is an expression like `x * x`, the key will be the string `"x * x"`.

  *Returns:* The value

* **give(x, y, z)**

  Multiple arguments can be given. The above is equivalent to `give(x=x, y=y, z=z)`.

  *Returns:* None

* **x = value; give()**

  If `give` has no arguments at all, it will look at the immediately previous statement and infer what you mean. The above is equivalent to `x = value; give(x=value)`.

  *Returns:* None


## Important functions and methods

* [print](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.print) and [display](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.display): for printing out the stream
* [values](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.values) and [accum](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.accum): for accumulating into a list
* [subscribe](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.subscribe) and [ksubscribe](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.ksubscribe): perform a task on every element
* [where](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.where), [where_any](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.where_any), [keep](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.keep), `gv["key"]`, `gv["?key"]`: filter based on keys

[See here for more details.](https://giving.readthedocs.io/en/latest/guide.html#important-methods)


## Operator summary

Not all operators are listed here. [See here](https://giving.readthedocs.io/en/latest/ref-operators.html) for the complete list.

### Filtering

* [filter](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.filter): filter with a function
* [kfilter](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.kfilter): filter with a function (keyword arguments)
* [where](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.where): filter based on keys and simple conditions
* [where_any](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.where_any): filter based on keys
* [keep](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.keep): filter based on keys (+drop the rest)
* [distinct](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.distinct): only emit distinct elements
* [norepeat](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.norepeat): only emit distinct consecutive elements
* [first](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.first): only emit the first element
* [last](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.last): only emit the last element
* [take](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.take): only emit the first n elements
* [take_last](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.take_last): only emit the last n elements
* [skip](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.skip): suppress the first n elements
* [skip_last](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.skip_last): suppress the last n elements

### Mapping

* [map](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.map): map with a function
* [kmap](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.kmap): map with a function (keyword arguments)
* [augment](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.augment): add extra keys using a mapping function
* [getitem](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.getitem): extract value for a specific key
* [sole](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.sole): extract value from dict of length 1
* [as_](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.as_): wrap as a dict

### Reduction

* [reduce](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.reduce): reduce with a function
* [scan](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.scan): emit a result at each reduction step
* [roll](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.roll): reduce using overlapping windows
* [kmerge](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.kmerge): merge all dictionaries in the stream
* [kscan](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.kscan): incremental version of ``kmerge``

### Arithmetic reductions

Most of these reductions can be called with the ``scan`` argument set to ``True`` to use ``scan`` instead of ``reduce``. ``scan`` can also be set to an integer, in which case ``roll`` is used.

* [average](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.average)
* [average_and_variance](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.average_and_variance)
* [count](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.count)
* [max](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.max)
* [min](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.min)
* [sum](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.sum)
* [variance](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.variance)

### Wrapping

* [wrap](https://giving.readthedocs.io/en/latest/ref-gvr.html#giving.gvr.Giver.wrap): give a special key at the beginning and end of a block
* [wrap_inherit](https://giving.readthedocs.io/en/latest/ref-gvr.html#giving.gvr.Giver.wrap_inherit): give a special key at the beginning and end of a block
* [inherit](https://giving.readthedocs.io/en/latest/ref-gvr.html#giving.gvr.Giver.inherit): add default key/values for every give() in the block
* [wrap](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.wrap): plug a context manager at the location of a ``give.wrap``
* [kwrap](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.kwrap): same as wrap, but pass kwargs

### Timing

* [debounce](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.debounce): suppress events that are too close in time
* [sample](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.sample): sample an element every n seconds
* [throttle](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.throttle): emit at most once every n seconds

### Debugging

* [breakpoint](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.breakpoint): set a breakpoint whenever data comes in. Use this with filters.
* [tag](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.tag): assigns a special word to every entry. Use with ``breakword``.
* [breakword](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.breakword): set a breakpoint on a specific word set by ``tag``, using the ``BREAKWORD`` environment variable.

### Other

* [accum](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.accum): accumulate into a list
* [display](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.display): print out the stream (pretty).
* [print](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.print): print out the stream.
* [values](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.values): accumulate into a list (context manager)
* [subscribe](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.subscribe): run a task on every element
* [ksubscribe](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.ksubscribe): run a task on every element (keyword arguments)


## ML ideas

Here are some ideas for using giving in a machine learning model training context:

```python
from giving import give, given


def main():
    model = Model()

    for i in range(niters):
        # Give the model. give looks at the argument string, so 
        # give(model) is equivalent to give(model=model)
        give(model)

        loss = model.step()

        # Give the iteration number and the loss (equivalent to give(i=i, loss=loss))
        give(i, loss)

    # Give the final model. The final=True key is there so we can filter on it.
    give(model, final=True)


if __name__ == "__main__":
    with given() as gv:
        # ===========================================================
        # Define our pipeline **before** running main()
        # ===========================================================

        # Filter all the lines that have the "loss" key
        # NOTE: Same as gv.filter(lambda values: "loss" in values)
        losses = gv.where("loss")

        # Print the losses on stdout
        losses.display()                 # always
        losses.throttle(1).display()     # OR: once every second
        losses.slice(step=10).display()  # OR: every 10th loss

        # Log the losses (and indexes i) with wandb
        # >> is shorthand for .subscribe()
        losses >> wandb.log

        # Print the minimum loss at the end
        losses["loss"].min().print("Minimum loss: {}")

        # Print the mean of the last 100 losses
        # * affix adds columns, so we will display i, loss and meanloss together
        # * The scan argument outputs the mean incrementally
        # * It's important that each affixed column has the same length as
        #   the losses stream (or "table")
        losses.affix(meanloss=losses["loss"].mean(scan=100)).display()

        # Store all the losses in a list
        losslist = losses["loss"].accum()

        # Set a breakpoint whenever the loss is nan or infinite
        losses["loss"].filter(lambda loss: not math.isfinite(loss)).breakpoint()


        # Filter all the lines that have the "model" key:
        models = gv.where("model")

        # Write a checkpoint of the model at most once every 30 minutes
        models["model"].throttle(30 * 60).subscribe(
            lambda model: model.checkpoint()
        )

        # Watch with wandb, but only once at the very beginning
        models["model"].first() >> wandb.watch

        # Write the final model (you could also use models.last())
        models.where(final=True)["model"].subscribe(
            lambda model: model.save()
        )


        # ===========================================================
        # Finally, execute the code. All the pipelines we defined above
        # will proceed as we give data.
        # ===========================================================
        main()
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/breuleux/giving",
    "name": "giving",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7,<4.0",
    "maintainer_email": "",
    "keywords": "",
    "author": "Olivier Breuleux",
    "author_email": "breuleux@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/62/c6/c105bfac8d97b58f191f1e128593ae693e7e5d41066d637e7874342d1f13/giving-0.4.2.tar.gz",
    "platform": null,
    "description": "\n# giving \u2014 the reactive logger\n\n[Documentation](https://giving.readthedocs.io)\n\n`giving` is a simple, magical library that lets you log or \"give\" arbitrary data throughout a program and then process it as an event stream. You can use it to log to the terminal, to [wandb](https://wandb.ai/site) or [mlflow](https://mlflow.org/), to compute minimums, maximums, rolling means, etc., separate from your program's core logic.\n\n1. Inside your code, **`give()`** every object or datum that you may want to log or compute metrics about.\n2. Wrap your main loop with **`given()`** and define pipelines to map, filter and reduce the data you gave.\n\n\n## Examples\n\n\n<table>\n<tr>\n<th>Code</th>\n<th>Output</th>\n</tr>\n\n<!-- ROW -->\n\n<tr>\n<td>\n\nSimple logging\n\n```python\n# All calls to give() will log to the configured console\nwith given().display():\n    a, b = 10, 20\n    # Without parameters: last expression + result\n    give()\n    # With parameters:\n    # parameter is just value: value => value\n    # parameter is key and value: key => value\n    give(a * b, c=30)\n```\n\n</td>\n<td>\n\n```\na: 10; b: 20\na * b: 200; c: 30\n```\n\n</td>\n</tr>\n<tr></tr>\n\n<!-- ROW -->\n\n<tr>\n<td>\n\nExtract values into a list\n\n```python\n# give(key=value) with key == \"s\" will add value to `results`\nwith given()[\"s\"].values() as results:\n    s = 0\n    for i in range(5):\n        s += i\n        give(s)\n\nprint(results)\n```\n\n</td>\n<td>\n\n```\n[0, 1, 3, 6, 10]\n```\n\n</td>\n</tr>\n<tr></tr>\n\n<!-- ROW -->\n\n<tr>\n<td>\n\nReductions (min, max, count, etc.)\n\n```python\ndef collatz(n):\n    while n != 1:\n        give(n)\n        n = (3 * n + 1) if n % 2 else (n // 2)\n\nwith given() as gv:\n    gv[\"n\"].max().print(\"max: {}\")\n    gv[\"n\"].count().print(\"steps: {}\")\n\n    collatz(2021)\n```\n\n</td>\n<td>\n\n```\nmax: 6064\nsteps: 63\n```\n\n</td>\n</tr>\n<tr></tr>\n\n<!-- ROW -->\n\n<tr>\n<td>\n\nUsing the `eval` method instead of `with`:\n\n```python\nst, = given()[\"n\"].count().eval(collatz, 2021)\nprint(st)\n```\n\n</td>\n<td>\n\n```\n63\n```\n\n</td>\n</tr>\n<tr></tr>\n\n<!-- ROW -->\n\n<tr>\n<td>\n\nThe `kscan` method\n\n```python\nwith given() as gv:\n    gv.kscan().display()\n\n    give(elk=1)\n    give(rabbit=2)\n    give(elk=3, wolf=4)\n```\n\n</td>\n<td>\n\n```\nelk: 1\nelk: 1; rabbit: 2\nelk: 3; rabbit: 2; wolf: 4\n```\n\n</td>\n</tr>\n<tr></tr>\n\n<!-- ROW -->\n\n<tr>\n<td>\n\nThe `throttle` method\n\n```python\nwith given() as gv:\n    gv.throttle(1).display()\n\n    for i in range(50):\n        give(i)\n        time.sleep(0.1)\n```\n\n</td>\n<td>\n\n```\ni: 0\ni: 10\ni: 20\ni: 30\ni: 40\n```\n\n</td>\n</tr>\n<tr></tr>\n\n</table>\n\nThe above examples only show a small number of [all the available operators](https://giving.readthedocs.io/en/latest/ref-operators.html).\n\n\n## Give\n\nThere are multiple ways you can use `give`. `give` returns None *unless* it is given a single positional argument, in which case it returns the value of that argument.\n\n* **give(key=value)**\n\n  This is the most straightforward way to use `give`: you write out both the key and the value associated.\n\n  *Returns:* None\n\n* **x = give(value)**\n\n  When no key is given, but the result of `give` is assigned to a variable, the key is the name of that variable. In other words, the above is equivalent to `give(x=value)`.\n\n  *Returns:* The value\n\n* **give(x)**\n\n  When no key is given and the result is *not* assigned to a variable, `give(x)` is equivalent to `give(x=x)`. If the argument is an expression like `x * x`, the key will be the string `\"x * x\"`.\n\n  *Returns:* The value\n\n* **give(x, y, z)**\n\n  Multiple arguments can be given. The above is equivalent to `give(x=x, y=y, z=z)`.\n\n  *Returns:* None\n\n* **x = value; give()**\n\n  If `give` has no arguments at all, it will look at the immediately previous statement and infer what you mean. The above is equivalent to `x = value; give(x=value)`.\n\n  *Returns:* None\n\n\n## Important functions and methods\n\n* [print](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.print) and [display](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.display): for printing out the stream\n* [values](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.values) and [accum](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.accum): for accumulating into a list\n* [subscribe](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.subscribe) and [ksubscribe](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.ksubscribe): perform a task on every element\n* [where](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.where), [where_any](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.where_any), [keep](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.keep), `gv[\"key\"]`, `gv[\"?key\"]`: filter based on keys\n\n[See here for more details.](https://giving.readthedocs.io/en/latest/guide.html#important-methods)\n\n\n## Operator summary\n\nNot all operators are listed here. [See here](https://giving.readthedocs.io/en/latest/ref-operators.html) for the complete list.\n\n### Filtering\n\n* [filter](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.filter): filter with a function\n* [kfilter](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.kfilter): filter with a function (keyword arguments)\n* [where](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.where): filter based on keys and simple conditions\n* [where_any](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.where_any): filter based on keys\n* [keep](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.keep): filter based on keys (+drop the rest)\n* [distinct](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.distinct): only emit distinct elements\n* [norepeat](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.norepeat): only emit distinct consecutive elements\n* [first](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.first): only emit the first element\n* [last](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.last): only emit the last element\n* [take](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.take): only emit the first n elements\n* [take_last](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.take_last): only emit the last n elements\n* [skip](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.skip): suppress the first n elements\n* [skip_last](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.skip_last): suppress the last n elements\n\n### Mapping\n\n* [map](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.map): map with a function\n* [kmap](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.kmap): map with a function (keyword arguments)\n* [augment](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.augment): add extra keys using a mapping function\n* [getitem](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.getitem): extract value for a specific key\n* [sole](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.sole): extract value from dict of length 1\n* [as_](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.as_): wrap as a dict\n\n### Reduction\n\n* [reduce](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.reduce): reduce with a function\n* [scan](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.scan): emit a result at each reduction step\n* [roll](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.roll): reduce using overlapping windows\n* [kmerge](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.kmerge): merge all dictionaries in the stream\n* [kscan](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.kscan): incremental version of ``kmerge``\n\n### Arithmetic reductions\n\nMost of these reductions can be called with the ``scan`` argument set to ``True`` to use ``scan`` instead of ``reduce``. ``scan`` can also be set to an integer, in which case ``roll`` is used.\n\n* [average](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.average)\n* [average_and_variance](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.average_and_variance)\n* [count](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.count)\n* [max](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.max)\n* [min](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.min)\n* [sum](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.sum)\n* [variance](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.variance)\n\n### Wrapping\n\n* [wrap](https://giving.readthedocs.io/en/latest/ref-gvr.html#giving.gvr.Giver.wrap): give a special key at the beginning and end of a block\n* [wrap_inherit](https://giving.readthedocs.io/en/latest/ref-gvr.html#giving.gvr.Giver.wrap_inherit): give a special key at the beginning and end of a block\n* [inherit](https://giving.readthedocs.io/en/latest/ref-gvr.html#giving.gvr.Giver.inherit): add default key/values for every give() in the block\n* [wrap](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.wrap): plug a context manager at the location of a ``give.wrap``\n* [kwrap](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.kwrap): same as wrap, but pass kwargs\n\n### Timing\n\n* [debounce](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.debounce): suppress events that are too close in time\n* [sample](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.sample): sample an element every n seconds\n* [throttle](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.throttle): emit at most once every n seconds\n\n### Debugging\n\n* [breakpoint](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.breakpoint): set a breakpoint whenever data comes in. Use this with filters.\n* [tag](https://giving.readthedocs.io/en/latest/ref-operators.html#giving.operators.tag): assigns a special word to every entry. Use with ``breakword``.\n* [breakword](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.breakword): set a breakpoint on a specific word set by ``tag``, using the ``BREAKWORD`` environment variable.\n\n### Other\n\n* [accum](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.accum): accumulate into a list\n* [display](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.display): print out the stream (pretty).\n* [print](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.print): print out the stream.\n* [values](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.values): accumulate into a list (context manager)\n* [subscribe](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.subscribe): run a task on every element\n* [ksubscribe](https://giving.readthedocs.io/en/latest/ref-gvn.html#giving.gvn.Given.ksubscribe): run a task on every element (keyword arguments)\n\n\n## ML ideas\n\nHere are some ideas for using giving in a machine learning model training context:\n\n```python\nfrom giving import give, given\n\n\ndef main():\n    model = Model()\n\n    for i in range(niters):\n        # Give the model. give looks at the argument string, so \n        # give(model) is equivalent to give(model=model)\n        give(model)\n\n        loss = model.step()\n\n        # Give the iteration number and the loss (equivalent to give(i=i, loss=loss))\n        give(i, loss)\n\n    # Give the final model. The final=True key is there so we can filter on it.\n    give(model, final=True)\n\n\nif __name__ == \"__main__\":\n    with given() as gv:\n        # ===========================================================\n        # Define our pipeline **before** running main()\n        # ===========================================================\n\n        # Filter all the lines that have the \"loss\" key\n        # NOTE: Same as gv.filter(lambda values: \"loss\" in values)\n        losses = gv.where(\"loss\")\n\n        # Print the losses on stdout\n        losses.display()                 # always\n        losses.throttle(1).display()     # OR: once every second\n        losses.slice(step=10).display()  # OR: every 10th loss\n\n        # Log the losses (and indexes i) with wandb\n        # >> is shorthand for .subscribe()\n        losses >> wandb.log\n\n        # Print the minimum loss at the end\n        losses[\"loss\"].min().print(\"Minimum loss: {}\")\n\n        # Print the mean of the last 100 losses\n        # * affix adds columns, so we will display i, loss and meanloss together\n        # * The scan argument outputs the mean incrementally\n        # * It's important that each affixed column has the same length as\n        #   the losses stream (or \"table\")\n        losses.affix(meanloss=losses[\"loss\"].mean(scan=100)).display()\n\n        # Store all the losses in a list\n        losslist = losses[\"loss\"].accum()\n\n        # Set a breakpoint whenever the loss is nan or infinite\n        losses[\"loss\"].filter(lambda loss: not math.isfinite(loss)).breakpoint()\n\n\n        # Filter all the lines that have the \"model\" key:\n        models = gv.where(\"model\")\n\n        # Write a checkpoint of the model at most once every 30 minutes\n        models[\"model\"].throttle(30 * 60).subscribe(\n            lambda model: model.checkpoint()\n        )\n\n        # Watch with wandb, but only once at the very beginning\n        models[\"model\"].first() >> wandb.watch\n\n        # Write the final model (you could also use models.last())\n        models.where(final=True)[\"model\"].subscribe(\n            lambda model: model.save()\n        )\n\n\n        # ===========================================================\n        # Finally, execute the code. All the pipelines we defined above\n        # will proceed as we give data.\n        # ===========================================================\n        main()\n```\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Reactive logging",
    "version": "0.4.2",
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "59fde61d8f83d3ff67a689eec21a89df0e97fbe8df06aa349c6c6f8d0c1b8f6c",
                "md5": "f8486e72ca5f0c8d3ac8a860bafefcf8",
                "sha256": "24c239fd6d3b58e38c1c847b7b553f8d8c9474f9f479341c56dead82facdf2fd"
            },
            "downloads": -1,
            "filename": "giving-0.4.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "f8486e72ca5f0c8d3ac8a860bafefcf8",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7,<4.0",
            "size": 28647,
            "upload_time": "2023-03-24T19:32:14",
            "upload_time_iso_8601": "2023-03-24T19:32:14.440919Z",
            "url": "https://files.pythonhosted.org/packages/59/fd/e61d8f83d3ff67a689eec21a89df0e97fbe8df06aa349c6c6f8d0c1b8f6c/giving-0.4.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "62c6c105bfac8d97b58f191f1e128593ae693e7e5d41066d637e7874342d1f13",
                "md5": "978a5ce7bc7e435cb822625cafab0bff",
                "sha256": "d122c73b4c7d6ba7da277ac104ef3fce24e0ba3ff165427032d6446a129563e8"
            },
            "downloads": -1,
            "filename": "giving-0.4.2.tar.gz",
            "has_sig": false,
            "md5_digest": "978a5ce7bc7e435cb822625cafab0bff",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7,<4.0",
            "size": 30159,
            "upload_time": "2023-03-24T19:32:15",
            "upload_time_iso_8601": "2023-03-24T19:32:15.747085Z",
            "url": "https://files.pythonhosted.org/packages/62/c6/c105bfac8d97b58f191f1e128593ae693e7e5d41066d637e7874342d1f13/giving-0.4.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-03-24 19:32:15",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "breuleux",
    "github_project": "giving",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "giving"
}
        
Elapsed time: 0.06100s