progiter


Nameprogiter JSON
Version 2.0.0 PyPI version JSON
download
home_page
SummaryA single-threaded alternative to tqdm.
upload_time2023-06-11 21:57:41
maintainer
docs_urlNone
authorJon Crall
requires_python>=3.6
licenseApache 2
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            |GithubActions| |ReadTheDocs| |Pypi| |Downloads| |Codecov|


ProgIter
========

ProgIter lets you measure and print the progress of an iterative process. This
can be done either via an iterable interface or using the manual API. Using the
iterable interface is most common.

.. .. animation generated via: dev/maintain/record_animation_demo.sh

.. .. image:: https://i.imgur.com/HoJJYzd.gif
.. image:: https://i.imgur.com/Jqfg8w0.gif
   :height: 300px
   :align: left

Basic usage is:

.. code:: python

    >>> from progiter import ProgIter
    >>> for n in ProgIter(range(1000)):
    >>>     ...  # do some work


The basic ProgIter is *unthreaded*. This differentiates it from
`tqdm <https://github.com/tqdm/tqdm>`_ and
`rich.progress <https://rich.readthedocs.io/en/stable/progress.html>`_
which use a *threaded* implementation.
The choice of implementation has different tradeoffs and neither is strictly
better than the other.
An unthreaded progress bar provides synchronous uncluttered logging, increased
stability, and --- unintuitively ---- speed (due to Python's GIL).
Meanwhile threaded progress bars are more responsive, able to update multiple
stdout lines at a time, and can look prettier (unless you try to log stdout to
disk).

ProgIter was originally developed independently of ``tqdm``, but the newer
versions of this library have been designed to be compatible with tqdm-API.
``ProgIter`` is now a (mostly) drop-in alternative to ``tqdm``.
The ``tqdm`` library may be more appropriate in some cases.
The main advantage of ``ProgIter`` is that it does not use any python
threading, and therefore can be safer with code that makes heavy use of
multiprocessing.
`The reason <https://pybay.com/site_media/slides/raymond2017-keynote/combo.html>`_
for this is that threading before forking may cause locks to be duplicated
across processes, which may lead to deadlocks (although with tqdm this is very
unlikely).

ProgIter is simpler than tqdm, which may be desirable for some applications.
However, this also means ProgIter is not as extensible as tqdm.
If you want a pretty bar or need something fancy, use tqdm (or rich);
if you want useful information  about your iteration by default, use progiter.

New in Version 2.0, ``progiter.ProgressManager``, which enables near-seemless
toggling between an unthreaded ``ProgIter`` backend and a threaded
``RichProgIter`` backend. Basic usage is:

.. code:: python

    from progiter.manager import ProgressManager
    pman = ProgressManager()
    with pman:
        for item in pman.progiter(range(1000)):
            ...  # do some work


The following gif illustrates this and more complex usage:

.. image:: https://i.imgur.com/GE1h3kr.gif
   :height: 501px
   :align: left

Package level documentation can be found at: https://progiter.readthedocs.io/en/latest/

Example
-------

The basic usage of ProgIter is simple and intuitive: wrap a python iterable.
The following example wraps a ``range`` iterable and reports progress to stdout
as the iterable is consumed. The ``ProgIter`` object accepts various keyword
arguments to modify the details of how progress is measured and reported. See
API documentation of the ``ProgIter`` class here:
https://progiter.readthedocs.io/en/latest/progiter.progiter.html#progiter.progiter.ProgIter


.. code:: python

    >>> from progiter import ProgIter
    >>> def is_prime(n):
    ...     return n >= 2 and not any(n % i == 0 for i in range(2, n))
    >>> for n in ProgIter(range(1000), verbose=2):
    >>>     # do some work
    >>>     is_prime(n)
    0.00%    0/1000... rate=0 Hz, eta=?, total=0:00:00
    0.60%    6/1000... rate=76995.12 Hz, eta=0:00:00, total=0:00:00
    100.00% 1000/1000... rate=266488.22 Hz, eta=0:00:00, total=0:00:00


For more complex applications is may sometimes be desireable to manually use
the ProgIter API. This is done as follows:

.. code:: python

    >>> from progiter import ProgIter
    >>> n = 3
    >>> prog = ProgIter(desc='manual', total=n, verbose=3, time_thresh=0)
    >>> prog.begin() # Manually begin progress iteration
    >>> for _ in range(n):
    ...     prog.step(inc=1)  # specify the number of steps to increment
    >>> prog.end()  # Manually end progress iteration
    manual 0.00% 0/3... rate=0 Hz, eta=?, total=0:00:00
    manual 33.33% 1/3... rate=5422.82 Hz, eta=0:00:00, total=0:00:00
    manual 66.67% 2/3... rate=8907.61 Hz, eta=0:00:00, total=0:00:00
    manual 100.00% 3/3... rate=12248.15 Hz, eta=0:00:00, total=0:00:00


By default ``ProgIter`` aims to write a line to stdout once every two seconds
to minimize its overhead and reduce clutter. Setting this to zero will force
it to print on every iteration.


When working with ProgIter in either iterable or manual mode you can use the
``prog.ensure_newline`` method to guarantee that the next call you make to stdout
will start on a new line. You can also use the ``prog.set_extra`` method to
update a dynamic "extra" message that is shown in the formatted output. The
following example demonstrates this.


.. code:: python

    >>> from progiter import ProgIter
    >>> def is_prime(n):
    ...     return n >= 2 and not any(n % i == 0 for i in range(2, n))
    >>> _iter = range(1000)
    >>> prog = ProgIter(_iter, desc='check primes', verbose=2, time_thresh=1e-3)
    >>> for n in prog:
    >>>     if n == 97:
    >>>         print('!!! Special print at n=97 !!!')
    >>>     if is_prime(n):
    >>>         prog.set_extra('Biggest prime so far: {}'.format(n))
    >>>         prog.ensure_newline()
    check primes 0.00%    0/1000... rate=0 Hz, eta=?, total=0:00:00
    check primes 0.60%    6/1000...Biggest prime so far: 5 rate=79329.39 Hz, eta=0:00:00, total=0:00:00
    !!! Special print at n=97 !!!
    check primes 75.60%  756/1000...Biggest prime so far: 751 rate=272693.23 Hz, eta=0:00:00, total=0:00:00
    check primes 99.30%  993/1000...Biggest prime so far: 991 rate=245852.75 Hz, eta=0:00:00, total=0:00:00
    check primes 100.00% 1000/1000...Biggest prime so far: 997 rate=244317.84 Hz, eta=0:00:00, total=0:00:00


Installation
------------

ProgIter can be easily installed via `pip`.

.. code:: bash

   pip install progiter

Alternatively, the `ubelt`_ library ships with its own version of ProgIter.
Note that the `ubelt` version of progiter is distinct (i.e. ubelt actually
contains a copy of this library), but the two libraries are generally kept in
sync.


.. _ubelt: https://github.com/Erotemic/ubelt


.. |Travis| image:: https://img.shields.io/travis/Erotemic/progiter/master.svg?label=Travis%20CI
   :target: https://travis-ci.org/Erotemic/progiter?branch=master
.. |Codecov| image:: https://codecov.io/github/Erotemic/progiter/badge.svg?branch=master&service=github
   :target: https://codecov.io/github/Erotemic/progiter?branch=master
.. |Appveyor| image:: https://ci.appveyor.com/api/projects/status/github/Erotemic/progiter?branch=master&svg=True
   :target: https://ci.appveyor.com/project/Erotemic/progiter/branch/master
.. |Pypi| image:: https://img.shields.io/pypi/v/progiter.svg
   :target: https://pypi.python.org/pypi/progiter
.. |Downloads| image:: https://img.shields.io/pypi/dm/progiter.svg
   :target: https://pypistats.org/packages/progiter
.. |CircleCI| image:: https://circleci.com/gh/Erotemic/progiter.svg?style=svg
    :target: https://circleci.com/gh/Erotemic/progiter
.. |ReadTheDocs| image:: https://readthedocs.org/projects/progiter/badge/?version=latest
    :target: http://progiter.readthedocs.io/en/latest/
.. |GithubActions| image:: https://github.com/Erotemic/progiter/actions/workflows/tests.yml/badge.svg?branch=main
    :target: https://github.com/Erotemic/progiter/actions?query=branch%3Amain



            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "progiter",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": "",
    "keywords": "",
    "author": "Jon Crall",
    "author_email": "erotemic@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/02/42/c7ea4b181feadb567ced59636ba72bfd307aa2a00d83c22e38b7d823fc3e/progiter-2.0.0.tar.gz",
    "platform": null,
    "description": "|GithubActions| |ReadTheDocs| |Pypi| |Downloads| |Codecov|\n\n\nProgIter\n========\n\nProgIter lets you measure and print the progress of an iterative process. This\ncan be done either via an iterable interface or using the manual API. Using the\niterable interface is most common.\n\n.. .. animation generated via: dev/maintain/record_animation_demo.sh\n\n.. .. image:: https://i.imgur.com/HoJJYzd.gif\n.. image:: https://i.imgur.com/Jqfg8w0.gif\n   :height: 300px\n   :align: left\n\nBasic usage is:\n\n.. code:: python\n\n    >>> from progiter import ProgIter\n    >>> for n in ProgIter(range(1000)):\n    >>>     ...  # do some work\n\n\nThe basic ProgIter is *unthreaded*. This differentiates it from\n`tqdm <https://github.com/tqdm/tqdm>`_ and\n`rich.progress <https://rich.readthedocs.io/en/stable/progress.html>`_\nwhich use a *threaded* implementation.\nThe choice of implementation has different tradeoffs and neither is strictly\nbetter than the other.\nAn unthreaded progress bar provides synchronous uncluttered logging, increased\nstability, and --- unintuitively ---- speed (due to Python's GIL).\nMeanwhile threaded progress bars are more responsive, able to update multiple\nstdout lines at a time, and can look prettier (unless you try to log stdout to\ndisk).\n\nProgIter was originally developed independently of ``tqdm``, but the newer\nversions of this library have been designed to be compatible with tqdm-API.\n``ProgIter`` is now a (mostly) drop-in alternative to ``tqdm``.\nThe ``tqdm`` library may be more appropriate in some cases.\nThe main advantage of ``ProgIter`` is that it does not use any python\nthreading, and therefore can be safer with code that makes heavy use of\nmultiprocessing.\n`The reason <https://pybay.com/site_media/slides/raymond2017-keynote/combo.html>`_\nfor this is that threading before forking may cause locks to be duplicated\nacross processes, which may lead to deadlocks (although with tqdm this is very\nunlikely).\n\nProgIter is simpler than tqdm, which may be desirable for some applications.\nHowever, this also means ProgIter is not as extensible as tqdm.\nIf you want a pretty bar or need something fancy, use tqdm (or rich);\nif you want useful information  about your iteration by default, use progiter.\n\nNew in Version 2.0, ``progiter.ProgressManager``, which enables near-seemless\ntoggling between an unthreaded ``ProgIter`` backend and a threaded\n``RichProgIter`` backend. Basic usage is:\n\n.. code:: python\n\n    from progiter.manager import ProgressManager\n    pman = ProgressManager()\n    with pman:\n        for item in pman.progiter(range(1000)):\n            ...  # do some work\n\n\nThe following gif illustrates this and more complex usage:\n\n.. image:: https://i.imgur.com/GE1h3kr.gif\n   :height: 501px\n   :align: left\n\nPackage level documentation can be found at: https://progiter.readthedocs.io/en/latest/\n\nExample\n-------\n\nThe basic usage of ProgIter is simple and intuitive: wrap a python iterable.\nThe following example wraps a ``range`` iterable and reports progress to stdout\nas the iterable is consumed. The ``ProgIter`` object accepts various keyword\narguments to modify the details of how progress is measured and reported. See\nAPI documentation of the ``ProgIter`` class here:\nhttps://progiter.readthedocs.io/en/latest/progiter.progiter.html#progiter.progiter.ProgIter\n\n\n.. code:: python\n\n    >>> from progiter import ProgIter\n    >>> def is_prime(n):\n    ...     return n >= 2 and not any(n % i == 0 for i in range(2, n))\n    >>> for n in ProgIter(range(1000), verbose=2):\n    >>>     # do some work\n    >>>     is_prime(n)\n    0.00%    0/1000... rate=0 Hz, eta=?, total=0:00:00\n    0.60%    6/1000... rate=76995.12 Hz, eta=0:00:00, total=0:00:00\n    100.00% 1000/1000... rate=266488.22 Hz, eta=0:00:00, total=0:00:00\n\n\nFor more complex applications is may sometimes be desireable to manually use\nthe ProgIter API. This is done as follows:\n\n.. code:: python\n\n    >>> from progiter import ProgIter\n    >>> n = 3\n    >>> prog = ProgIter(desc='manual', total=n, verbose=3, time_thresh=0)\n    >>> prog.begin() # Manually begin progress iteration\n    >>> for _ in range(n):\n    ...     prog.step(inc=1)  # specify the number of steps to increment\n    >>> prog.end()  # Manually end progress iteration\n    manual 0.00% 0/3... rate=0 Hz, eta=?, total=0:00:00\n    manual 33.33% 1/3... rate=5422.82 Hz, eta=0:00:00, total=0:00:00\n    manual 66.67% 2/3... rate=8907.61 Hz, eta=0:00:00, total=0:00:00\n    manual 100.00% 3/3... rate=12248.15 Hz, eta=0:00:00, total=0:00:00\n\n\nBy default ``ProgIter`` aims to write a line to stdout once every two seconds\nto minimize its overhead and reduce clutter. Setting this to zero will force\nit to print on every iteration.\n\n\nWhen working with ProgIter in either iterable or manual mode you can use the\n``prog.ensure_newline`` method to guarantee that the next call you make to stdout\nwill start on a new line. You can also use the ``prog.set_extra`` method to\nupdate a dynamic \"extra\" message that is shown in the formatted output. The\nfollowing example demonstrates this.\n\n\n.. code:: python\n\n    >>> from progiter import ProgIter\n    >>> def is_prime(n):\n    ...     return n >= 2 and not any(n % i == 0 for i in range(2, n))\n    >>> _iter = range(1000)\n    >>> prog = ProgIter(_iter, desc='check primes', verbose=2, time_thresh=1e-3)\n    >>> for n in prog:\n    >>>     if n == 97:\n    >>>         print('!!! Special print at n=97 !!!')\n    >>>     if is_prime(n):\n    >>>         prog.set_extra('Biggest prime so far: {}'.format(n))\n    >>>         prog.ensure_newline()\n    check primes 0.00%    0/1000... rate=0 Hz, eta=?, total=0:00:00\n    check primes 0.60%    6/1000...Biggest prime so far: 5 rate=79329.39 Hz, eta=0:00:00, total=0:00:00\n    !!! Special print at n=97 !!!\n    check primes 75.60%  756/1000...Biggest prime so far: 751 rate=272693.23 Hz, eta=0:00:00, total=0:00:00\n    check primes 99.30%  993/1000...Biggest prime so far: 991 rate=245852.75 Hz, eta=0:00:00, total=0:00:00\n    check primes 100.00% 1000/1000...Biggest prime so far: 997 rate=244317.84 Hz, eta=0:00:00, total=0:00:00\n\n\nInstallation\n------------\n\nProgIter can be easily installed via `pip`.\n\n.. code:: bash\n\n   pip install progiter\n\nAlternatively, the `ubelt`_ library ships with its own version of ProgIter.\nNote that the `ubelt` version of progiter is distinct (i.e. ubelt actually\ncontains a copy of this library), but the two libraries are generally kept in\nsync.\n\n\n.. _ubelt: https://github.com/Erotemic/ubelt\n\n\n.. |Travis| image:: https://img.shields.io/travis/Erotemic/progiter/master.svg?label=Travis%20CI\n   :target: https://travis-ci.org/Erotemic/progiter?branch=master\n.. |Codecov| image:: https://codecov.io/github/Erotemic/progiter/badge.svg?branch=master&service=github\n   :target: https://codecov.io/github/Erotemic/progiter?branch=master\n.. |Appveyor| image:: https://ci.appveyor.com/api/projects/status/github/Erotemic/progiter?branch=master&svg=True\n   :target: https://ci.appveyor.com/project/Erotemic/progiter/branch/master\n.. |Pypi| image:: https://img.shields.io/pypi/v/progiter.svg\n   :target: https://pypi.python.org/pypi/progiter\n.. |Downloads| image:: https://img.shields.io/pypi/dm/progiter.svg\n   :target: https://pypistats.org/packages/progiter\n.. |CircleCI| image:: https://circleci.com/gh/Erotemic/progiter.svg?style=svg\n    :target: https://circleci.com/gh/Erotemic/progiter\n.. |ReadTheDocs| image:: https://readthedocs.org/projects/progiter/badge/?version=latest\n    :target: http://progiter.readthedocs.io/en/latest/\n.. |GithubActions| image:: https://github.com/Erotemic/progiter/actions/workflows/tests.yml/badge.svg?branch=main\n    :target: https://github.com/Erotemic/progiter/actions?query=branch%3Amain\n\n\n",
    "bugtrack_url": null,
    "license": "Apache 2",
    "summary": "A single-threaded alternative to tqdm.",
    "version": "2.0.0",
    "project_urls": null,
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c4d5981d5651ecf71f47aeeecdb99b175daa1bfb2e157253e8c016a6515bf63e",
                "md5": "09dfd71b0472f386beb9dc9452546895",
                "sha256": "66ab3aa88f804e969477ad9de52926a08c2d5b673d324132cfe1530888e26f10"
            },
            "downloads": -1,
            "filename": "progiter-2.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "09dfd71b0472f386beb9dc9452546895",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 24863,
            "upload_time": "2023-06-11T21:57:39",
            "upload_time_iso_8601": "2023-06-11T21:57:39.360328Z",
            "url": "https://files.pythonhosted.org/packages/c4/d5/981d5651ecf71f47aeeecdb99b175daa1bfb2e157253e8c016a6515bf63e/progiter-2.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0242c7ea4b181feadb567ced59636ba72bfd307aa2a00d83c22e38b7d823fc3e",
                "md5": "dd4cf8c7f0d6482245fa261db1b54a95",
                "sha256": "155b17bf3f090c3791219a2fce37769c96852b38f62ea9baf9162c731e8870e4"
            },
            "downloads": -1,
            "filename": "progiter-2.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "dd4cf8c7f0d6482245fa261db1b54a95",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6",
            "size": 28068,
            "upload_time": "2023-06-11T21:57:41",
            "upload_time_iso_8601": "2023-06-11T21:57:41.172575Z",
            "url": "https://files.pythonhosted.org/packages/02/42/c7ea4b181feadb567ced59636ba72bfd307aa2a00d83c22e38b7d823fc3e/progiter-2.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-06-11 21:57:41",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "progiter"
}
        
Elapsed time: 0.07762s