async-cast


Nameasync-cast JSON
Version 0.6.1 PyPI version JSON
download
home_pagehttps://github.com/joaduo/async_cast
SummaryCast an async function to blocking function and viceversa. Also use threads pools if needed.
upload_time2023-12-19 09:41:59
maintainer
docs_urlNone
authorJoaquin Duo
requires_python
licenseMIT
keywords asyncio async sync casting threads
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            async_cast
==========

|.github/workflows/tests.yml|

Cast async function to blocking and viceversa. (works on python 3.7 and
up) Also run functions in threads, whether async or blocking.

Why ``async_cast``?
-------------------

I found the current ``asyncio`` tools frustrating when migrating from
blocking code. If you want to profit IO operations to *“run something
else”* you need to rewrite all code to use asyncio. When you start form
scratch that’s acceptable, but not with legacy code.

So with this small self-contained library you can easily convert legacy
code into async code. The best way is running several blocking function
in different threads. But **be aware** that threads also bring race
conditions, so make sure concurrent functions are thread-safe.

Installing
----------

https://pypi.org/project/async-cast/

::

   pip install -U async-cast

The package is a single module that you can easily audit.

Decorator: casting ``async`` function to a blocking function
------------------------------------------------------------

.. code:: python

   from async_cast import also_blocking

   @also_blocking
   async def request_url(url, **kwargs):
       print(f'Requesting {url} with options {kwargs}')
       ...
       result = f'<h1>{url}</h1>'
       return result

   if __name__ == '__main__':
       print(request_url.blocking('https://github.com'))

Decorator: casting a blocking function to ``async`` function
------------------------------------------------------------

.. code:: python

   from async_cast import also_async
   import asyncio

   @also_async
   def request_url(url, **kwargs):
       print(f'Requesting {url} with options {kwargs}')
       ...
       result = f'<h1>{url}</h1>'
       return result

   async def main():
       print(await request_url.async_('https://github.com'))

   if __name__ == '__main__':
       asyncio.run(main())

Running tasks in a ThreadPool
-----------------------------

I wrapped existing ``ThreadPoolExecutor`` to make it easier to run tasks
inside it. Tasks are automatically registered in the pool declared by
the ``with thread_pool(...):`` context.

Running ``async`` function in threadpool
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code:: python

   from async_cast import also_blocking, thread_pool
   import asyncio

   @also_blocking
   async def request_url(url, **kwargs):
       print(f'Requesting {url} with options {kwargs}')
       ...
       result = f'<h1>{url}</h1>'
       return result

   async def main():
       with thread_pool(3):
           t1 = request_url.async_thread('https://github.com')
           t2 = request_url.async_thread('https://google.com')
           t3 = request_url.async_thread('https://facebook.com')
           results = await asyncio.gather(t1,t2,t3)
           print(results)

   if __name__ == '__main__':
       asyncio.run(main())

Running blocking function in threadpool
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code:: python

   from async_cast import also_async, thread_pool
   import asyncio

   @also_async
   def request_url(url, **kwargs):
       print(f'Requesting {url} with options {kwargs}')
       ...
       result = f'<h1>{url}</h1>'
       return result

   async def main():
       with thread_pool(3):
           t1 = request_url.async_thread('https://github.com')
           t2 = request_url.async_thread('https://google.com')
           t3 = request_url.async_thread('https://facebook.com')
           results = await asyncio.gather(t1,t2,t3)
           print(results)

   if __name__ == '__main__':
       asyncio.run(main())

Non decorators alternatives
---------------------------

Casting ``async`` function to a blocking function with ``to_blocking``
----------------------------------------------------------------------

.. code:: python

   from async_cast import to_blocking

   async def request_url(url, **kwargs):
       print(f'Requesting {url} with options {kwargs}')
       ...
       result = f'<h1>{url}</h1>'
       return result

   if __name__ == '__main__':
       print(to_blocking(request_url)('https://github.com'))

Casting a blocking function to ``async`` function with ``to_async``
-------------------------------------------------------------------

.. code:: python

   from async_cast import to_async
   import asyncio

   def request_url(url, **kwargs):
       print(f'Requesting {url} with options {kwargs}')
       ...
       result = f'<h1>{url}</h1>'
       return result

   async def main():
       print(await to_async(request_url)('https://github.com'))

   if __name__ == '__main__':
       asyncio.run(main())

Running ``async`` or blocking function in threadpool with ``to_async_thread``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code:: python

   from async_cast import to_async_thread, thread_pool
   import asyncio

   async def request_url(url, **kwargs):
       print(f'Requesting {url} with options {kwargs}')
       ...
       result = f'<h1>{url}</h1>'
       return result

   def request_url_blocking(url, **kwargs):
       print(f'Requesting {url} with options {kwargs}')
       ...
       result = f'<h1>{url}</h1>'
       return result

   async def main():
       with thread_pool(3):
           t1 = to_async_thread(request_url)('https://github.com')
           t2 = to_async_thread(request_url)('https://google.com')
           t3 = to_async_thread(request_url)('https://facebook.com')
           t4 = to_async_thread(request_url_blocking)('https://duckduckgo.com')
           results = await asyncio.gather(t1,t2,t3,t4)
           print(results)

   if __name__ == '__main__':
       asyncio.run(main())

.. |.github/workflows/tests.yml| image:: https://github.com/joaduo/async_cast/actions/workflows/tests.yml/badge.svg
   :target: https://github.com/joaduo/async_cast/actions/workflows/tests.yml



            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/joaduo/async_cast",
    "name": "async-cast",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "asyncio,async,sync,casting,threads",
    "author": "Joaquin Duo",
    "author_email": "joaduo@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/f5/29/81488908353cc406212f8decde1ae624704b5d499fd09df7a36b1a476fbd/async_cast-0.6.1.tar.gz",
    "platform": null,
    "description": "async_cast\n==========\n\n|.github/workflows/tests.yml|\n\nCast async function to blocking and viceversa. (works on python 3.7 and\nup) Also run functions in threads, whether async or blocking.\n\nWhy ``async_cast``?\n-------------------\n\nI found the current ``asyncio`` tools frustrating when migrating from\nblocking code. If you want to profit IO operations to *\u201crun something\nelse\u201d* you need to rewrite all code to use asyncio. When you start form\nscratch that\u2019s acceptable, but not with legacy code.\n\nSo with this small self-contained library you can easily convert legacy\ncode into async code. The best way is running several blocking function\nin different threads. But **be aware** that threads also bring race\nconditions, so make sure concurrent functions are thread-safe.\n\nInstalling\n----------\n\nhttps://pypi.org/project/async-cast/\n\n::\n\n   pip install -U async-cast\n\nThe package is a single module that you can easily audit.\n\nDecorator: casting ``async`` function to a blocking function\n------------------------------------------------------------\n\n.. code:: python\n\n   from async_cast import also_blocking\n\n   @also_blocking\n   async def request_url(url, **kwargs):\n       print(f'Requesting {url} with options {kwargs}')\n       ...\n       result = f'<h1>{url}</h1>'\n       return result\n\n   if __name__ == '__main__':\n       print(request_url.blocking('https://github.com'))\n\nDecorator: casting a blocking function to ``async`` function\n------------------------------------------------------------\n\n.. code:: python\n\n   from async_cast import also_async\n   import asyncio\n\n   @also_async\n   def request_url(url, **kwargs):\n       print(f'Requesting {url} with options {kwargs}')\n       ...\n       result = f'<h1>{url}</h1>'\n       return result\n\n   async def main():\n       print(await request_url.async_('https://github.com'))\n\n   if __name__ == '__main__':\n       asyncio.run(main())\n\nRunning tasks in a ThreadPool\n-----------------------------\n\nI wrapped existing ``ThreadPoolExecutor`` to make it easier to run tasks\ninside it. Tasks are automatically registered in the pool declared by\nthe ``with thread_pool(...):`` context.\n\nRunning ``async`` function in threadpool\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code:: python\n\n   from async_cast import also_blocking, thread_pool\n   import asyncio\n\n   @also_blocking\n   async def request_url(url, **kwargs):\n       print(f'Requesting {url} with options {kwargs}')\n       ...\n       result = f'<h1>{url}</h1>'\n       return result\n\n   async def main():\n       with thread_pool(3):\n           t1 = request_url.async_thread('https://github.com')\n           t2 = request_url.async_thread('https://google.com')\n           t3 = request_url.async_thread('https://facebook.com')\n           results = await asyncio.gather(t1,t2,t3)\n           print(results)\n\n   if __name__ == '__main__':\n       asyncio.run(main())\n\nRunning blocking function in threadpool\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code:: python\n\n   from async_cast import also_async, thread_pool\n   import asyncio\n\n   @also_async\n   def request_url(url, **kwargs):\n       print(f'Requesting {url} with options {kwargs}')\n       ...\n       result = f'<h1>{url}</h1>'\n       return result\n\n   async def main():\n       with thread_pool(3):\n           t1 = request_url.async_thread('https://github.com')\n           t2 = request_url.async_thread('https://google.com')\n           t3 = request_url.async_thread('https://facebook.com')\n           results = await asyncio.gather(t1,t2,t3)\n           print(results)\n\n   if __name__ == '__main__':\n       asyncio.run(main())\n\nNon decorators alternatives\n---------------------------\n\nCasting ``async`` function to a blocking function with ``to_blocking``\n----------------------------------------------------------------------\n\n.. code:: python\n\n   from async_cast import to_blocking\n\n   async def request_url(url, **kwargs):\n       print(f'Requesting {url} with options {kwargs}')\n       ...\n       result = f'<h1>{url}</h1>'\n       return result\n\n   if __name__ == '__main__':\n       print(to_blocking(request_url)('https://github.com'))\n\nCasting a blocking function to ``async`` function with ``to_async``\n-------------------------------------------------------------------\n\n.. code:: python\n\n   from async_cast import to_async\n   import asyncio\n\n   def request_url(url, **kwargs):\n       print(f'Requesting {url} with options {kwargs}')\n       ...\n       result = f'<h1>{url}</h1>'\n       return result\n\n   async def main():\n       print(await to_async(request_url)('https://github.com'))\n\n   if __name__ == '__main__':\n       asyncio.run(main())\n\nRunning ``async`` or blocking function in threadpool with ``to_async_thread``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code:: python\n\n   from async_cast import to_async_thread, thread_pool\n   import asyncio\n\n   async def request_url(url, **kwargs):\n       print(f'Requesting {url} with options {kwargs}')\n       ...\n       result = f'<h1>{url}</h1>'\n       return result\n\n   def request_url_blocking(url, **kwargs):\n       print(f'Requesting {url} with options {kwargs}')\n       ...\n       result = f'<h1>{url}</h1>'\n       return result\n\n   async def main():\n       with thread_pool(3):\n           t1 = to_async_thread(request_url)('https://github.com')\n           t2 = to_async_thread(request_url)('https://google.com')\n           t3 = to_async_thread(request_url)('https://facebook.com')\n           t4 = to_async_thread(request_url_blocking)('https://duckduckgo.com')\n           results = await asyncio.gather(t1,t2,t3,t4)\n           print(results)\n\n   if __name__ == '__main__':\n       asyncio.run(main())\n\n.. |.github/workflows/tests.yml| image:: https://github.com/joaduo/async_cast/actions/workflows/tests.yml/badge.svg\n   :target: https://github.com/joaduo/async_cast/actions/workflows/tests.yml\n\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Cast an async function to blocking function and viceversa. Also use threads pools if needed.",
    "version": "0.6.1",
    "project_urls": {
        "Homepage": "https://github.com/joaduo/async_cast"
    },
    "split_keywords": [
        "asyncio",
        "async",
        "sync",
        "casting",
        "threads"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "f52981488908353cc406212f8decde1ae624704b5d499fd09df7a36b1a476fbd",
                "md5": "fd5ec095e7276cd6cc922b8f04c05100",
                "sha256": "42edcba10e06bd919a8462f12c4b30909c3d936cf00b38cea0ce111ef2440659"
            },
            "downloads": -1,
            "filename": "async_cast-0.6.1.tar.gz",
            "has_sig": false,
            "md5_digest": "fd5ec095e7276cd6cc922b8f04c05100",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 4511,
            "upload_time": "2023-12-19T09:41:59",
            "upload_time_iso_8601": "2023-12-19T09:41:59.371469Z",
            "url": "https://files.pythonhosted.org/packages/f5/29/81488908353cc406212f8decde1ae624704b5d499fd09df7a36b1a476fbd/async_cast-0.6.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-12-19 09:41:59",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "joaduo",
    "github_project": "async_cast",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "async-cast"
}
        
Elapsed time: 0.15807s