async-tkinter-loop


Nameasync-tkinter-loop JSON
Version 0.10.2 PyPI version JSON
download
home_pageNone
SummaryAsynchronous mainloop implementation for tkinter
upload_time2025-10-16 16:55:58
maintainerNone
docs_urlNone
authorinsolor
requires_python<4.0,>=3.10
licenseMIT
keywords tkinter async async-await asyncio aiohttp
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Asynchronous Tkinter Mainloop

[![Python tests](https://github.com/insolor/async-tkinter-loop/actions/workflows/python-tests.yml/badge.svg)](https://github.com/insolor/async-tkinter-loop/actions/workflows/python-tests.yml)
[![Documentation](https://github.com/insolor/async-tkinter-loop/actions/workflows/deploy-docs.yml/badge.svg)](https://insolor.github.io/async-tkinter-loop/)
[![Coverage Status](https://coveralls.io/repos/github/insolor/async-tkinter-loop/badge.svg?branch=main)](https://coveralls.io/github/insolor/async-tkinter-loop?branch=main)
[![Maintainability](https://qlty.sh/badges/01e7abf5-a53c-42ce-a0e1-c1b0bd24d095/maintainability.svg)](https://qlty.sh/gh/insolor/projects/async-tkinter-loop)  
[![PyPI](https://img.shields.io/pypi/v/async-tkinter-loop)](https://pypi.org/project/async-tkinter-loop/)
![Supported Python versions](https://img.shields.io/pypi/pyversions/async-tkinter-loop)
<!--![PyPI - Downloads](https://img.shields.io/pypi/dm/async-tkinter-loop)-->

Implementation of asynchronous `mainloop` for tkinter, the use of which allows using `async` handler functions.
It is intended to be as simple to use as possible. No fancy unusual syntax or constructions - just use an alternative
function instead of `root.mainloop()` and wrap asynchronous handlers into a helper function.

> **Note**  
> Please, fill free to [report bugs](https://github.com/insolor/async-tkinter-loop/issues), add [pull requests](https://github.com/insolor/async-tkinter-loop/pulls) or [share your thoughts / ask questions, etc.](https://github.com/insolor/async-tkinter-loop/discussions) about the module.

Based on ideas from:

* my answer on ru.stackoverflow.com: <https://ru.stackoverflow.com/a/1043146>
* answer of [Terry Jan Reedy](https://stackoverflow.com/users/722804) on stackoverflow.com:
  <https://stackoverflow.com/a/47896365>
* answer of [jfs](https://ru.stackoverflow.com/users/23044) on ru.stackoverflow.com:
  <https://ru.stackoverflow.com/a/804609>

## Installation

Install the package with the following command:

```
pip install async-tkinter-loop
```
or
```
pip install async-tkinter-loop[examples]
```

- `[examples]` part is needed to install optional dependencies (such as `httpx` and `pillow`) to run some of the
  examples. If you're not going to run examples, remove the `[examples]` part from the command
- Use `pip3` instead of `pip` on Linux systems to install the package for python3 (not python2)
- Probably you'll want to create a virtual environment for experiments with this library, but this is optional.
- If you want to try examples, download the entire repository as an archive (green "code" button on
  [the GitHub page](https://github.com/insolor/async-tkinter-loop) →
  "Download ZIP"), unpack, run any example (of course, you need to install optional dependencies)

## Some examples

Basic example:
```python
import asyncio
import tkinter as tk

from async_tkinter_loop import async_handler, async_mainloop


async def counter():
    i = 0
    while True:
        i += 1
        label.config(text=str(i))
        await asyncio.sleep(1.0)


root = tk.Tk()

label = tk.Label(root)
label.pack()

tk.Button(root, text="Start", command=async_handler(counter)).pack()

async_mainloop(root)
```

Also, `async_handler` function can be used as a decorator (but it makes a decorated function syncroneous):

```python
import asyncio
import tkinter as tk

from async_tkinter_loop import async_handler, async_mainloop


@async_handler
async def counter():
    i = 0
    while True:
        i += 1
        label.config(text=str(i))
        await asyncio.sleep(1.0)


root = tk.Tk()

label = tk.Label(root)
label.pack()

tk.Button(root, text="Start", command=counter).pack()

async_mainloop(root)
```

A more practical example, downloading an image from the Internet with [httpx](https://github.com/encode/httpx)
(you can use [aiohttp](https://github.com/aio-libs/aiohttp) as well)
and displaying it in the Tkinter window:

```python
import tkinter as tk
from io import BytesIO

import httpx
from PIL import Image, ImageTk

from async_tkinter_loop import async_handler, async_mainloop


async def load_image(url):
    button.config(state=tk.DISABLED)
    label.config(text="Loading...", image="")

    async with httpx.AsyncClient() as client:
        response = await client.get(url, follow_redirects=True)
        if response.status_code != 200:
            label.config(text=f"HTTP error {response.status_code}")
        else:
            content = response.content
            pil_image = Image.open(BytesIO(content))
            image = ImageTk.PhotoImage(pil_image)
            label.image = image
            label.config(image=image, text="")

        button.config(state=tk.NORMAL)


url = "https://picsum.photos/800/640"

root = tk.Tk()
root.geometry("800x640")

button = tk.Button(root, text="Load an image", command=async_handler(load_image, url))
button.pack()

label = tk.Label(root)
label.pack(expand=1, fill=tk.BOTH)

async_mainloop(root)
```

More examples see in the [`examples`](https://github.com/insolor/async-tkinter-loop/tree/main/examples) directory.


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "async-tkinter-loop",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.10",
    "maintainer_email": null,
    "keywords": "tkinter, async, async-await, asyncio, aiohttp",
    "author": "insolor",
    "author_email": "insolor@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/07/71/0bbbf6f5d53e165f200e2b4015f210180282087a7719fb89cd27b2ce334e/async_tkinter_loop-0.10.2.tar.gz",
    "platform": null,
    "description": "# Asynchronous Tkinter Mainloop\n\n[![Python tests](https://github.com/insolor/async-tkinter-loop/actions/workflows/python-tests.yml/badge.svg)](https://github.com/insolor/async-tkinter-loop/actions/workflows/python-tests.yml)\n[![Documentation](https://github.com/insolor/async-tkinter-loop/actions/workflows/deploy-docs.yml/badge.svg)](https://insolor.github.io/async-tkinter-loop/)\n[![Coverage Status](https://coveralls.io/repos/github/insolor/async-tkinter-loop/badge.svg?branch=main)](https://coveralls.io/github/insolor/async-tkinter-loop?branch=main)\n[![Maintainability](https://qlty.sh/badges/01e7abf5-a53c-42ce-a0e1-c1b0bd24d095/maintainability.svg)](https://qlty.sh/gh/insolor/projects/async-tkinter-loop)  \n[![PyPI](https://img.shields.io/pypi/v/async-tkinter-loop)](https://pypi.org/project/async-tkinter-loop/)\n![Supported Python versions](https://img.shields.io/pypi/pyversions/async-tkinter-loop)\n<!--![PyPI - Downloads](https://img.shields.io/pypi/dm/async-tkinter-loop)-->\n\nImplementation of asynchronous `mainloop` for tkinter, the use of which allows using `async` handler functions.\nIt is intended to be as simple to use as possible. No fancy unusual syntax or constructions - just use an alternative\nfunction instead of `root.mainloop()` and wrap asynchronous handlers into a helper function.\n\n> **Note**  \n> Please, fill free to [report bugs](https://github.com/insolor/async-tkinter-loop/issues), add [pull requests](https://github.com/insolor/async-tkinter-loop/pulls) or [share your thoughts / ask questions, etc.](https://github.com/insolor/async-tkinter-loop/discussions) about the module.\n\nBased on ideas from:\n\n* my answer on ru.stackoverflow.com: <https://ru.stackoverflow.com/a/1043146>\n* answer of [Terry Jan Reedy](https://stackoverflow.com/users/722804) on stackoverflow.com:\n  <https://stackoverflow.com/a/47896365>\n* answer of [jfs](https://ru.stackoverflow.com/users/23044) on ru.stackoverflow.com:\n  <https://ru.stackoverflow.com/a/804609>\n\n## Installation\n\nInstall the package with the following command:\n\n```\npip install async-tkinter-loop\n```\nor\n```\npip install async-tkinter-loop[examples]\n```\n\n- `[examples]` part is needed to install optional dependencies (such as `httpx` and `pillow`) to run some of the\n  examples. If you're not going to run examples, remove the `[examples]` part from the command\n- Use `pip3` instead of `pip` on Linux systems to install the package for python3 (not python2)\n- Probably you'll want to create a virtual environment for experiments with this library, but this is optional.\n- If you want to try examples, download the entire repository as an archive (green \"code\" button on\n  [the GitHub page](https://github.com/insolor/async-tkinter-loop) \u2192\n  \"Download ZIP\"), unpack, run any example (of course, you need to install optional dependencies)\n\n## Some examples\n\nBasic example:\n```python\nimport asyncio\nimport tkinter as tk\n\nfrom async_tkinter_loop import async_handler, async_mainloop\n\n\nasync def counter():\n    i = 0\n    while True:\n        i += 1\n        label.config(text=str(i))\n        await asyncio.sleep(1.0)\n\n\nroot = tk.Tk()\n\nlabel = tk.Label(root)\nlabel.pack()\n\ntk.Button(root, text=\"Start\", command=async_handler(counter)).pack()\n\nasync_mainloop(root)\n```\n\nAlso, `async_handler` function can be used as a decorator (but it makes a decorated function syncroneous):\n\n```python\nimport asyncio\nimport tkinter as tk\n\nfrom async_tkinter_loop import async_handler, async_mainloop\n\n\n@async_handler\nasync def counter():\n    i = 0\n    while True:\n        i += 1\n        label.config(text=str(i))\n        await asyncio.sleep(1.0)\n\n\nroot = tk.Tk()\n\nlabel = tk.Label(root)\nlabel.pack()\n\ntk.Button(root, text=\"Start\", command=counter).pack()\n\nasync_mainloop(root)\n```\n\nA more practical example, downloading an image from the Internet with [httpx](https://github.com/encode/httpx)\n(you can use [aiohttp](https://github.com/aio-libs/aiohttp) as well)\nand displaying it in the Tkinter window:\n\n```python\nimport tkinter as tk\nfrom io import BytesIO\n\nimport httpx\nfrom PIL import Image, ImageTk\n\nfrom async_tkinter_loop import async_handler, async_mainloop\n\n\nasync def load_image(url):\n    button.config(state=tk.DISABLED)\n    label.config(text=\"Loading...\", image=\"\")\n\n    async with httpx.AsyncClient() as client:\n        response = await client.get(url, follow_redirects=True)\n        if response.status_code != 200:\n            label.config(text=f\"HTTP error {response.status_code}\")\n        else:\n            content = response.content\n            pil_image = Image.open(BytesIO(content))\n            image = ImageTk.PhotoImage(pil_image)\n            label.image = image\n            label.config(image=image, text=\"\")\n\n        button.config(state=tk.NORMAL)\n\n\nurl = \"https://picsum.photos/800/640\"\n\nroot = tk.Tk()\nroot.geometry(\"800x640\")\n\nbutton = tk.Button(root, text=\"Load an image\", command=async_handler(load_image, url))\nbutton.pack()\n\nlabel = tk.Label(root)\nlabel.pack(expand=1, fill=tk.BOTH)\n\nasync_mainloop(root)\n```\n\nMore examples see in the [`examples`](https://github.com/insolor/async-tkinter-loop/tree/main/examples) directory.\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Asynchronous mainloop implementation for tkinter",
    "version": "0.10.2",
    "project_urls": {
        "Documentation": "https://insolor.github.io/async-tkinter-loop/",
        "Homepage": "https://github.com/insolor/async-tkinter-loop",
        "Repository": "https://github.com/insolor/async-tkinter-loop"
    },
    "split_keywords": [
        "tkinter",
        " async",
        " async-await",
        " asyncio",
        " aiohttp"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "75d001a81c450393e32d14ed0d1d040f01fb45cf019ca5cf83002440c0820c7e",
                "md5": "598d703ecf9a565ac102c6f6fdd6147c",
                "sha256": "8f87e1090c298f3cb0b66871e4f14669a7a82d438ef05a2046b2da37f907bd8b"
            },
            "downloads": -1,
            "filename": "async_tkinter_loop-0.10.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "598d703ecf9a565ac102c6f6fdd6147c",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.10",
            "size": 6061,
            "upload_time": "2025-10-16T16:55:57",
            "upload_time_iso_8601": "2025-10-16T16:55:57.240890Z",
            "url": "https://files.pythonhosted.org/packages/75/d0/01a81c450393e32d14ed0d1d040f01fb45cf019ca5cf83002440c0820c7e/async_tkinter_loop-0.10.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "07710bbbf6f5d53e165f200e2b4015f210180282087a7719fb89cd27b2ce334e",
                "md5": "aa9cf0ba10b2259db3b33ab3cd919d10",
                "sha256": "d84a302c357794cf215e8e4ab9f749dc6a05323102f7176ca2d3b5fea47da0fb"
            },
            "downloads": -1,
            "filename": "async_tkinter_loop-0.10.2.tar.gz",
            "has_sig": false,
            "md5_digest": "aa9cf0ba10b2259db3b33ab3cd919d10",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.10",
            "size": 5213,
            "upload_time": "2025-10-16T16:55:58",
            "upload_time_iso_8601": "2025-10-16T16:55:58.510408Z",
            "url": "https://files.pythonhosted.org/packages/07/71/0bbbf6f5d53e165f200e2b4015f210180282087a7719fb89cd27b2ce334e/async_tkinter_loop-0.10.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-16 16:55:58",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "insolor",
    "github_project": "async-tkinter-loop",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "async-tkinter-loop"
}
        
Elapsed time: 1.70479s