In nicegui
, I have a button to start a function that creates a class. I want the button to be disabled during the creation of the class, which takes a few seconds in my real code (not the example I am posting here). I am using the nicegui
example: disable button with a context manager as a starting point. The class I create has an attribute that requires pythonnet
and the use of Decimal
module (from System
). I am not so familiar with pythonnet
, but the class works when I use it without the cpu_bound
function of nicegui
. Otherwise, I get a TypeError: cannot pickle 'Decimal' object
. As I understand, I need this cpu_bound
to disable my button during the class creation. How can I avoid the TypeError
above?
I have simplified my code as much as possible so that it still shows the error:
from contextlib import contextmanager
from nicegui import run, ui
import clr
from System import Decimal
@contextmanager
def disable(button: ui.button):
button.disable()
try:
yield
finally:
button.enable()
class my_class:
def __init__(self, value):
self.value = Decimal(value)
def some_function():
return my_class(1)
async def get_slow_response(button: ui.button) -> None:
with disable(button):
return_value = await run.cpu_bound(some_function)
ui.button('Get slow response', on_click=lambda e: get_slow_response(e.sender))
ui.run(port=80)
I'm not sure if it is related, but I noticed that to import Decimal
, I also need to have the import clr
and in VS Code, System carries a "could not be resolved" warning. Although, as I said, the class works fine in its own. Simply removing this Decimal
in the class fixes the issue, but then my class needs this attribute to be Decimal
so it can pass it to a DLL.
I am using pythonnet
3.0.3, nicegui
1.4.22 on Python 3.10.14 (I am on Windows if that matters).
I somehow managed to get the intended behavior using asyncio.to_thread
instead of run.cpu_bound
. The part with the contextmanager
didn't work anymore, but the code does what I want. I am not qualified to explain why it works but perhaps someone else can comment on this.
import asyncio
import clr
import time
from nicegui import ui
from System import Decimal
class my_class:
def __init__(self, value):
self.value = Decimal(value)
def some_function():
time.sleep(1)
return my_class(1)
async def get_slow_response(button: ui.button) -> None:
button.disable()
return_value = await asyncio.to_thread(some_function)
button.enable()
ui.button('Get slow response', on_click=lambda e: get_slow_response(e.sender))
ui.run(port=80)
I also documented this on the nicegui repo in discussion #2985.