Skip to main content

AsyncTkinter2

日本語版

asynctkinter2 is an async library that saves you from ugly callback-style code, like most of async libraries do. Let's say you want to do:

  1. print("A")
  2. wait for 1sec
  3. print("B")
  4. wait for a label to be pressed
  5. print("C")

in that order. Your code would look like this:

def what_you_want_to_do(label):
    bind_id = None
    print("A")

    def one_sec_lator(__):
        nonlocal bind_id
        print("B")
        bind_id = label.bind("<ButtonPress>", on_press, "+")
    label.after(1000, one_sec_lator)

    def on_press(event):
        label.unbind("<ButtonPress>", bind_id)
        print("C")

what_you_want_to_do(...)

This is hard to follow. With asynctkinter2, the same logic becomes:

import asynctkinter2 as atk

async def what_you_want_to_do(label):
    print("A")
    await atk.sleep(label.after, 1000)
    print("B")
    await atk.event(label, "<ButtonPress>")
    print("C")

# WARNING: In a real app, you should use "structured concurrency" APIs instead of `start`.
atk.start(what_you_want_to_do(...))

Installation

Pin the minor version.

pip install "asynctkinter2>=0.2,<0.3"

Example

from functools import partial
import tkinter as tk
import asynctkinter2 as atk


def main():
    root = tk.Tk()
    root_task = atk.start(async_main(root))
    root.protocol("WM_DELETE_WINDOW", lambda: (root_task.cancel(), root.destroy()))
    root.mainloop()


async def async_main(root: tk.Tk):
    sleep = partial(atk.sleep, root.after)
    label = tk.Label(root, text='Hello', font=('', 80))
    label.pack()

    # Waits for 2 seconds to elapse.
    await sleep(2000)

    # Waits for a label to be pressed.
    event = await atk.event(label, "<ButtonPress>")
    print(f"pos: {event.x}, {event.y}")

    # Waits for either 5 seconds to elapse or a label to be pressed.
    # i.e. Waits at most 5 seconds for a label to be pressed.
    tasks = await atk.wait_any(
        sleep(5000),
        atk.event(label, "<ButtonPress>"),
    )
    if tasks[0].finished:
        print("Timeout")
    else:
        event = tasks[1].result
        print(f"Label pressed (pos: {event.x}, {event.y})")

    # Waits for both 5 seconds to elapse and a label to be pressed.
    tasks = await atk.wait_all(
        sleep(5000),
        atk.event(label, "<ButtonPress>"),
    )

    # Performs an HTTP request without freezing the UI, then waits for completion.
    import requests
    res: requests.Response = await atk.run_in_thread(
        root.after, lambda: requests.get("https://httpbin.org/delay/2"))


if __name__ == "__main__":
    main()

Differences from asynctkinter

asynctkinter:

  • Uses its own main loop instead of tkinter's built-in mainloop()
  • Uses its own timer mechanism instead of tkinter's built-in after()

asynctkinter2 doesn't do that and relies entirely on tkinter's built-in components.

Coexisting with asyncio

Coexistence does come with one important limitation: you cannot mix asyncio async operations and asynctkinter2 async operations inside the same async function:

async def this_does_not_work():
    await asyncio.sleep(1)
    await asynctkinter2.sleep(widget.after, 1000)

"Async operation" here means only code that uses the Python keywords async or await. The following is fine because, although it uses both asyncio and asynctkinter2, the asynctkinter2 side does not involve async/await:

async def this_works():
    await asyncio.sleep(1)
    task = asynctkinter2.start(...)
    e = asynctkinter2.Event()
    e.fire()

asyncio.create_task(this_works())

The next example is also fine because the asyncio side does not involve async/await:

async def this_also_works():
    task = asyncio.create_task(...)
    e = asyncio.Event()
    e.set()
    await asynctkinter2.sleep(widget.after, 1000)

asynctkinter2.start(this_also_works())

Metadata

Release files for asynctkinter2 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for asynctkinter2 0.2.0
File Size Uploaded
asynctkinter2-0.2.0.tar.gz 4.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for asynctkinter2 0.2.0
File Interpreter ABI Platform
asynctkinter2-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 9.3 kB

Release files / asynctkinter2-0.2.0.tar.gz

Download URL asynctkinter2-0.2.0.tar.gz
Size 4.2 kB
Tags Source
SHA-256 checksum
How to use checksums
d614e424c9ffe7da8d339914243f1a34b4cca42afea2b829aeb5d3dfb0b9da2d
BLAKE2b-256 checksum
How to use checksums
6905b0e8653d96bab2484e73d659c3abdbdbe977e20a32e7b6dd90fd195149da
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 24, 2026.

Transparency log

Release files / asynctkinter2-0.2.0-py3-none-any.whl

Download URL asynctkinter2-0.2.0-py3-none-any.whl
Size 5.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2f5951791ede88526771a973c8b2d6c1aa9b2f9530a8fee49ba1de3e114faa4b
BLAKE2b-256 checksum
How to use checksums
f282664a7050366ac204b75fb2f92fac42a42bc046a59aeae17f653279f72d55
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page