Как установить реактивное значение из обратного вызова в нереактивном модуле?Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Как установить реактивное значение из обратного вызова в нереактивном модуле?

Сообщение Anonymous »

Я строю приложение, используя Shiny для Python и tinkerforge аппаратные модули. Я отделил весь код, связанный с аппаратным обеспечением, в класс и создал его экземпляр при запуске приложения. Таким образом, я могу выполнить функцию всякий раз, когда кнопка меняет состояние. Однако кажется, что, хотя я могу использовать глобальные переменные в рамках обратного вызова, то же самое не относится к реактивным значениям. «Нет текущего реактивного контекста».
Итак, как я могу использовать этот обратный вызов, чтобы запустить события в блестящем приложении?# TinkerforgeModule.py
from tinkerforge.ip_connection import IPConnection
from tinkerforge.bricklet_rgb_led_button import BrickletRGBLEDButton

class TinkerforgeModule (object):
def __init__(self):
ipcon = IPConnection() # Create IP connection to tinkerforge
self.rgb_button = BrickletRGBLEDButton('24fu', ipcon)
ipcon.connect('127.0.0.1', 4223)

def register_hw_button_cb(self, func):
self.rgb_button.register_callback(
BrickletRGBLEDButton.CALLBACK_BUTTON_STATE_CHANGED,
func
)
< /code>
# app.py
from shiny import App, ui, render, reactive
from datetime import datetime
import TinkerforgeModule

app_ui = ui.page_auto(
ui.output_text("result_output")
)

def server(input, output, session):

hw_button_last_press = None
triggerMe = reactive.value(None)

def hw_button_callback(state):
global hw_button_last_press
if state == 1: # BrickletRGBLEDButton.BUTTON_STATE_RELEASED = 1
press_time = datetime.now() - hw_button_last_press
print(f"Button released after {press_time} seconds.")

# The line below does not work
# triggerMe.set(f"Button released after {press_time} seconds.")

else: # BrickletRGBLEDButton.BUTTON_STATE_PRESSED = 0
hw_button_last_press = datetime.now()
print("Button pressed.")

# The line below does not work
# triggerMe.set("Button pressed.")

tfm = TinkerforgeModule.TinkerforgeModule()
tfm.register_hw_button_cb(hw_button_callback)

@output
@render.text
def result_output():
return(f"Message: {triggerMe()}")

app = App(app_ui, server)
< /code>
Registering the callback works, the printing happens when the button is pressed and released. However when it comes to setting the reactive value the app crashes. Placing a breakpoint and executing step by step I get a RuntimeError: No current reactive context.
Первоначально я только что опробовал состояние кнопки каждые 50 мс, используя reactive.invalidate_later . Но обратный вызов был бы гораздо более чистым способом сделать это. Но, честно говоря, я не уверен, что это эквивалентно в отношении проблемы. В конце концов, он в конечном итоге создает ту же ошибку. Интересно, что ошибка «нет тока реактивного контекста» только появляется при чтении reactive.value, а не при его настройке. Это может быть связано с блестящей оценкой, хотя.
не вызывает print (triggerme.get ()) в конце hw_button_callback () приводит к сбою, но также не обновляется веб -интерфейс. Это просто продолжает вращать колесо ожидания. < /P>
# FakeTinkerforgeModule.py
import asyncio
from datetime import datetime

class FakeTinkerforgeModule (object):
def __init__(self):
asyncio.create_task(self.fake_button_trigger())

def register_hw_button_cb(self, func):
self.cb_func = func

async def fake_button_trigger(self):
await asyncio.sleep(2)
self.cb_func(0)
await asyncio.sleep(1)
self.cb_func(1)
< /code>
#app.py
from shiny import App, ui, render, reactive
from datetime import datetime
import FakeTinkerforgeModule

app_ui = ui.page_auto(
ui.output_text("result_output")
)

def server(input, output, session):

hw_button_last_press = None
triggerMe = reactive.value(None)

def hw_button_callback(state):
global hw_button_last_press
print(f"callback called, state: {state}")
if state == 1: # BrickletRGBLEDButton.BUTTON_STATE_RELEASED = 1
press_time = datetime.now() - hw_button_last_press
print(f"Button released after {press_time} seconds.")
triggerMe.set(f"Button released after {press_time} seconds.") # This part does not seem to have any effect, but also does not throw errors.

else: # BrickletRGBLEDButton.BUTTON_STATE_PRESSED = 0
hw_button_last_press = datetime.now()
print("Button pressed.")
triggerMe.set("Button pressed.") # This part does not seem to have any effect, but also does not throw errors.
print(triggerMe.get()) # This trigger RuntimeError("No current reactive context")

@output
@render.text
def result_output():
return(f"Message: {triggerMe()}")

tfm = TinkerforgeModule.TinkerforgeModule()
tfm.register_hw_button_cb(hw_button_callback)

app = App(app_ui, server)


Подробнее здесь: https://stackoverflow.com/questions/796 ... ive-module
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»