我想要:
- 從串口讀取(無限回圈)
- 當按下“停止”按鈕時 --> 停止讀取并繪制資料
從
uj5u.com熱心網友回復:
我認為問題就像在所有具有長時間運行代碼的 Python 腳本中一樣 - 它在一個執行緒中運行所有代碼,并且當它運行while True回圈(長時間運行代碼)時,它不能同時運行其他函式。
您可能必須在單獨的執行緒中運行您的函式 - 然后主執行緒可以執行on_button_clicked
這個版本適用于我:
from IPython.display import display
import ipywidgets as widgets
import time
import threading
button = widgets.Button(description="STOP!")
output = widgets.Output()
display(button, output)
break_cicle = True
def on_button_clicked(event):
global break_cicle
break_cicle = False
print("Button pressed: break_cicle:", break_cicle)
button.on_click(on_button_clicked)
def function():
while break_cicle:
print("While loop: break_cicle:", break_cicle)
time.sleep(1)
print("Done")
threading.Thread(target=function).start()
也許 Jupyter 有其他方法可以解決這個問題 - 即。當您使用asyncthen 撰寫函式時,您可以使用asyncio.sleep()which 讓 Python 在該函式處于休眠狀態時運行其他函式。
編輯:
在互聯網上挖掘(使用谷歌)我在 Jyputer 論壇上找到了帖子
執行長時間運行的單元格時的互動式小部件 - JupyterLab - Jupyter Community Forum
并且有指向模塊jupyter-ui-poll的鏈接,該模塊顯示了類似的示例(while-loop Button)并events用于此目的。當函式pull()執行時(在每個回圈中),Jupyter 可以將事件發送到小部件并且它有時間執行on_click()。
import time
from ipywidgets import Button
from jupyter_ui_poll import ui_events
# Set up simple GUI, button with on_click callback
# that sets ui_done=True and changes button text
ui_done = False
def on_click(btn):
global ui_done
ui_done = True
btn.description = '??'
btn = Button(description='Click Me')
btn.on_click(on_click)
display(btn)
# Wait for user to press the button
with ui_events() as poll:
while ui_done is False:
poll(10) # React to UI events (upto 10 at a time)
print('.', end='')
time.sleep(0.1)
print('done')
在源代碼中,我可以看到它asyncio用于此目的。
編輯:
多處理版本
行程不共享變數,因此它需要Queue將資訊從一個行程發送到另一個行程。
示例將訊息從 發送button到function。如果您想從中發送訊息function,button那么最好使用第二個佇列。
from IPython.display import display
import ipywidgets as widgets
import time
import multiprocessing
button = widgets.Button(description="STOP!")
output = widgets.Output()
display(button, output)
queue = multiprocessing.Queue()
def on_button_clicked(event):
queue.put('stop')
print("Button pressed")
button.on_click(on_button_clicked)
def function(queue):
while True:
print("While loop")
time.sleep(1)
if not queue.empty():
msg = queue.get()
if msg == 'stop':
break
#if msg == 'other text':
# ...other code...
print("Done")
multiprocessing.Process(target=function, args=(queue,)).start()
或更類似于以前的
def function(queue):
break_cicle = True
while break_cicle:
print("While loop: break_cicle:", break_cicle)
time.sleep(1)
if (not queue.empty()) and (queue.get() == 'stop'):
break_cicle = False
print("Done")
編輯:
帶異步的版本
Jupyter already is running asynio event loop and I add async function to this loop. And function uses await functions like asyncio.sleep so asynio event loop has time to run other functions - but if function could run only standard (not async) functions then it wouldn't work.
from IPython.display import display
import ipywidgets as widgets
import asyncio
button = widgets.Button(description="STOP!")
output = widgets.Output()
display(button, output)
break_cicle = True
def on_button_clicked(event):
global break_cicle
break_cicle = False
print("Button pressed: break_cicle:", break_cicle)
button.on_click(on_button_clicked)
async def function(): # it has to be `async`
while break_cicle:
print("While loop: break_cicle:", break_cicle)
await asyncio.sleep(1) # it needs some `await` functions
print("Done")
loop = asyncio.get_event_loop()
t = loop.create_task(function()) # assign to variable if you don't want to see `<Task ...>` in output
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/433896.html
上一篇:單擊按鈕時如何設定狀態
