{ "info": { "author": "Radek Kysely", "author_email": "kyselyradek@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "AtomicLoop\n^^^^^^^^^^\n\n`show example <#getting-started>`_ | `jump to docs <#documentation>`_\n\nCreate atomic loop iterations (let the current iteration finish even when interrupted).\n\nA simple context manager that asynchronously listens to potential\n``SIGINT`` and ``SIGTERM`` and provides you with **plain boolean flag** that can be\nused to control the iteration flow of a ``while`` loop based on whether or not\nan interrupt/terminate signal was received.\n\nThis was formerly built for reinforcement learning library that trains its agents\nin iterations and has to gracefully finish the current running episode every time\nthe training is interrupted.\n\nIt will be most useful in similar use cases, but can be actually used for anything\nelse. Technically, any block of code that needs to run without an interruption.\n\nNote that you will still be able to kill the running process using ``SIGKILL``.\n\nGetting Started\n###############\n\n.. code-block:: shell\n\n\tpip3 install atomicloop\n\n\nThe following example loop runs 3 iterations, each lasting three seconds.\nYou can try interrupting one of the steps by pressing ``Ctrl+C`` (which sends\n``SIGINT`` to the process). You will see the signal feedback but the program\nwill wait for the current iteration to finish and exits **after** the loop\niteration is done.\n\nMoreover, you can see the context manager is aware whether or not it finished\ndue to an interruption.\n\n.. code-block:: python\n\n\timport time\n\tfrom atomicloop import AtomicLoop\n\n\n\t# Optional callback handlers ----------------------------------------\n\tdef on_signal(signal, frame):\n\tprint(f' Received signal: {signal}')\n\tprint(' Finishing current step before terminating')\n\n\n\tdef on_exit(was_interrupted):\n\tprint(' Ended training')\n\tprint(f' Interrupted? {was_interrupted}')\n\n\n\t# Running the loop --------------------------------------------------\n\tgoal_steps = 3\n\n\twith AtomicLoop(on_signal, on_exit) as loop:\n\t\tstep_no = 0\n\t\twhile loop.run and step_no < goal_steps:\n\t\t\tprint(f'Starting training step #{step_no}')\n\t\t\ttime.sleep(3) # simulating some code execution\n\t\t\tprint(f'Finished training step #{step_no}')\n\t\t\tprint('----------------------------------\\n')\n\t\t\tstep_no += 1\n\n\nDocumentation\n#############\n\n``atomicloop.AtomicLoop(on_signal=None, on_end=None)``\n======================================================\n\nThe main and only class that creates the desired context manager.\n\n*on_signal* is a callable that gets invoked on incoming\n``SIGINT`` or ``SIGTERM``. It is called with 2 arguments:\nthe signal number and the current stack frame. For details\non the arguments, please consult *handler* part in\n`official signal.signal documentation\n`_.\n\n\n*on_end* is a callable that gets invoked *after* exiting\nthe context (after ``with`` block). It is called with\na single boolean argument stating whether or not the\nexecution was interrupted.\n\n``AtomicLoop()`` returns a new instance. To access the boolean\nflag for flow control, you have to read the flag as the instance's\nattribute.\n\nThe ``.run`` boolean flag states whether or not the program should\ncontinue its execution. It is ``True`` by default and switches to\n``False`` when an interruption signal was received.\n\nYou can also use one of many synonymous attributes:\n\n* ``loop.run``\n\n* ``loop.loop``\n\n* ``loop.move``\n\n* ``loop.cont``\n\n* ``loop.keep``\n\n* ``loop.keep_going``\n\n* ``loop.uninterrupted``\n\n", "description_content_type": "", "docs_url": null, "download_url": "https://pypi.org/project/atomicloop/", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/kysely/atomicloop", "keywords": "atomic,linearizable,undivisible,uninterruptible,atomic loop,atomic block,atomic operation,delayed interrupt,delayed keyboardinterrupt,keyboardinterrupt,SIGINT,SIGTERM", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "atomicloop", "package_url": "https://pypi.org/project/atomicloop/", "platform": "", "project_url": "https://pypi.org/project/atomicloop/", "project_urls": { "Download": "https://pypi.org/project/atomicloop/", "Homepage": "https://github.com/kysely/atomicloop" }, "release_url": "https://pypi.org/project/atomicloop/1.0.0/", "requires_dist": null, "requires_python": "", "summary": "Create atomic loop iterations (let the iteration finish even when interrupted)", "version": "1.0.0" }, "last_serial": 4039032, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "0149a05df00d006f07c8e90317e50dc5", "sha256": "383f2456a501643e73d771b8cf314f0c49e95057f07ab3d6ea7e74d7a3891bc8" }, "downloads": -1, "filename": "atomicloop-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "0149a05df00d006f07c8e90317e50dc5", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 4065, "upload_time": "2018-07-07T14:05:00", "url": "https://files.pythonhosted.org/packages/2d/6e/1a7982ebfaabe0ccc74a042b4cdd35f904484b8c3bb7d61bf97bf9e88067/atomicloop-0.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d8eb83935ac9111de280d447c77a7694", "sha256": "0ffd5f45a3576440f083e67f02b15cf9152c16bbdbc53d34f094b800b699ca69" }, "downloads": -1, "filename": "atomicloop-0.1.0.tar.gz", "has_sig": false, "md5_digest": "d8eb83935ac9111de280d447c77a7694", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4160, "upload_time": "2018-07-07T14:05:02", "url": "https://files.pythonhosted.org/packages/23/b2/6f70841db3a89ceaaa6a6c90229b8b12468bef81a32b97261d17da0926f6/atomicloop-0.1.0.tar.gz" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "66abb895b395b850f36a132cc98f570d", "sha256": "370bd80775bc072d06f4505b80c0096417654136fd46c3722b263bcca9777ac5" }, "downloads": -1, "filename": "atomicloop-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "66abb895b395b850f36a132cc98f570d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 4064, "upload_time": "2018-07-07T14:07:06", "url": "https://files.pythonhosted.org/packages/24/ca/d9fc4bd21de35633963dcdeb6efbb30ab5de740a4fa0c4157f2a9f3350b3/atomicloop-1.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "954c6ec0c627a922209d9b4ebf7b6ed7", "sha256": "5bc0934ac2b36f25b53f8fab692d94ce387c4fc548cd08de9e3cef5f64acb2c7" }, "downloads": -1, "filename": "atomicloop-1.0.0.tar.gz", "has_sig": false, "md5_digest": "954c6ec0c627a922209d9b4ebf7b6ed7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4157, "upload_time": "2018-07-07T14:07:07", "url": "https://files.pythonhosted.org/packages/0d/ef/3877b173ab2b5349bd95d05d5451a7aeefd6de3b64b7cc9c2bc08b88f4e6/atomicloop-1.0.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "66abb895b395b850f36a132cc98f570d", "sha256": "370bd80775bc072d06f4505b80c0096417654136fd46c3722b263bcca9777ac5" }, "downloads": -1, "filename": "atomicloop-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "66abb895b395b850f36a132cc98f570d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 4064, "upload_time": "2018-07-07T14:07:06", "url": "https://files.pythonhosted.org/packages/24/ca/d9fc4bd21de35633963dcdeb6efbb30ab5de740a4fa0c4157f2a9f3350b3/atomicloop-1.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "954c6ec0c627a922209d9b4ebf7b6ed7", "sha256": "5bc0934ac2b36f25b53f8fab692d94ce387c4fc548cd08de9e3cef5f64acb2c7" }, "downloads": -1, "filename": "atomicloop-1.0.0.tar.gz", "has_sig": false, "md5_digest": "954c6ec0c627a922209d9b4ebf7b6ed7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4157, "upload_time": "2018-07-07T14:07:07", "url": "https://files.pythonhosted.org/packages/0d/ef/3877b173ab2b5349bd95d05d5451a7aeefd6de3b64b7cc9c2bc08b88f4e6/atomicloop-1.0.0.tar.gz" } ] }