Skip to main content

async library for tkinter

Project description

AsyncTkinter

Youtube

asynctkinter 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_later(__):
        nonlocal bind_id
        print('B')
        bind_id = label.bind('<Button>', on_press, '+')
    label.after(1000, one_sec_later)

    def on_press(event):
        label.unbind('<Button>', bind_id)
        print('C')

what_you_want_to_do(...)

It's not easy to understand. If you use asynctkinter, the code above will become:

import asynctkinter as atk

async def what_you_want_to_do(clock, label):
    print('A')
    await clock.sleep(1)
    print('B')
    await atk.event(label, '<Button>')
    print('C')

atk.start(what_you_want_to_do(...))

Installation

Pin the minor version.

poetry add asynctkinter@~0.4
pip install "asynctkinter>=0.4,<0.5"

Usage

import tkinter as tk
import asynctkinter as atk


async def main(*, clock: atk.Clock, root: tk.Tk):
    label = tk.Label(root, text='Hello', font=('', 80))
    label.pack()

    # waits for 2 seconds to elapse
    await clock.sleep(2)

    # waits for a label to be pressed
    event = await atk.event(label, '<Button>')
    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(
        clock.sleep(5),
        atk.event(label, '<Button>'),
    )
    if tasks[0].finished:
        print("Timeout")
    else:
        event = tasks[1].result
        print(f"The label got pressed. (pos: {event.x}, {event.y})")

    # same as the above
    async with clock.move_on_after(5) as timeout_tracker:
        event = await atk.event(label, '<Button>')
        print(f"The label got pressed. (pos: {event.x}, {event.y})")
    if timeout_tracker.finished:
        print("Timeout")

    # waits for both 5 seconds to elapse and a label to be pressed.
    tasks = await atk.wait_all(
        clock.sleep(5),
        atk.event(label, '<Button>'),
    )

    # nests as you want.
    tasks = await ak.wait_all(
        atk.event(label, '<Button>'),
        atk.wait_any(
            clock.sleep(5),
            ...,
        ),
    )
    child_tasks = tasks[1].result


if __name__ == "__main__":
    atk.run(main)

threading

Unlike trio and asyncio, asynckivy does not provide any I/O primitives. Therefore, if you don’t want to implement your own, using threads may be the best way to perform I/O without blocking the main thread.

from concurrent.futures import ThreadPoolExecuter
import asynctkinter as atk

executer = ThreadPoolExecuter()

async def async_fn(clock: atk.Clock):
    # create a new thread, run a function inside it, then
    # wait for the completion of that thread
    r = await atk.run_in_thread(clock, thread_blocking_operation)
    print("return value:", r)

    # run a function inside a ThreadPoolExecuter, and wait for its completion.
    # (ProcessPoolExecuter is not supported)
    r = await atk.run_in_executer(clock, executer, thread_blocking_operation)
    print("return value:", r)

Unhandled exceptions (excluding BaseException that is not Exception) are propagated to the caller so you can catch them like you do in synchronous code:

import requests
import asynctkinter as atk

async def async_fn(clock: atk.Clock):
    try:
        r = await atk.run_in_thread(clock, lambda: requests.get('htt...', timeout=10), ...)
    except requests.Timeout:
        print("TIMEOUT!")
    else:
        print('RECEIVED:', r)

Notes

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

asynctkinter-0.4.3.tar.gz (5.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

asynctkinter-0.4.3-py3-none-any.whl (6.1 kB view details)

Uploaded Python 3

File details

Details for the file asynctkinter-0.4.3.tar.gz.

File metadata

  • Download URL: asynctkinter-0.4.3.tar.gz
  • Upload date:
  • Size: 5.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.4 CPython/3.11.4 Linux/5.4.0-216-generic

File hashes

Hashes for asynctkinter-0.4.3.tar.gz
Algorithm Hash digest
SHA256 22c729fda44846a7bb494108916796cfc2861dcec6d51ab91b42f5afa6367c8c
MD5 48d833c307e7fbda970fc36eb27318a7
BLAKE2b-256 70a71a5d75f862a19b549b0090779ff2f3b958d7b5ec9fa11ef351ce161f80f4

See more details on using hashes here.

File details

Details for the file asynctkinter-0.4.3-py3-none-any.whl.

File metadata

  • Download URL: asynctkinter-0.4.3-py3-none-any.whl
  • Upload date:
  • Size: 6.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.4 CPython/3.11.4 Linux/5.4.0-216-generic

File hashes

Hashes for asynctkinter-0.4.3-py3-none-any.whl
Algorithm Hash digest
SHA256 54971a72f5e2de04239e5909813c5ae7e24ea5f70af55a7b1a4b54146a346715
MD5 df18eeda0575916d36a8d5117a866e34
BLAKE2b-256 ef894bce1b25862ae90676157f8ebeef315920ce66139c84e4f6c5c71417ebe0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page