簡體   English   中英

如何在后台運行無限循環並停止它?

[英]How to run an infinite loop in background and stop it?

這是我的問題:使用Tkinter,我想單擊一個按鈕並啟動python腳本。 這個python腳本現在是導入到我的主腳本中的模塊(我不知道這是否是最好的方法)。 該腳本應在后台運行。 其中有一種方法可以將其退出。 我怎么稱呼它? 我想向模塊傳遞一個標志或其他東西,但是我不知道該怎么做。

現在,我這樣調用我的代碼:在gui.py中

import sniffer_wideband_v09
from Tkinter import *
root = Tk()
def handle_click():
    global t
    global stop_flag
    stop_flag = 0

    def callback():
        sniffer_wideband_v09.main(sampling_rates, center_frequencies, gains, file_dir, files_names) 
    t = Thread(target=callback)
    t.start()
root.mainloop()

我想在sniffer_wideband_v09.py中調用quitting()方法。 或將標志傳遞給我的模塊以停止無限循環。 之后,我將需要將所有這些綁定到Tkinter Buttons。

我對此問題進行了一些研究,發現:

有什么方法可以殺死Python中的線程嗎? 以及如何在tkinter的后台運行函數以及如何在python線程中運行和停止無限循環

首先是有希望的,但是我還不完全了解,我正在努力。

注意:我直接使用./gui.py從我的shell運行它,並且我在Ubuntu下而不是Windows下運行(我認為它可以改變處理多線程的某些方式)。

感謝您的閱讀,任何提示或幫助將不勝感激。 如果在此期間找到響應,我將發布我的代碼。

編輯:提供有關在線程中啟動的腳本的更多信息:(這是GNURadio腳本)

class foo():
    def __init__(self):
         self.parameters()
    def methods():
         self.dostuff()
def main(sampling_rates, center_frequencies, gains, file_dir, files_names):
    tb = foo()
    while True: #flag could be here to exit the infinite while.
         tb.start()
    tb.stop()
def quitting():
    tb.stop()
 ## not mandatory piece of code from now on
if __name = "__main__":
     main()
     quitting()

由於您的Tkinter gui應用程序和您從sniffer_wideband_09模塊調用的主要代碼之間沒有交互, sniffer_wideband_09我建議您使用多重處理:

import sniffer_wideband_v09
import multiprocessing
from Tkinter import *
root = Tk()
def handle_click():
    global t

    t = multiprocessing.Process(target=sniffer_wideband_v09.main, args=(sampling_rates, center_frequencies, gains, file_dir, files_names))
    t.start()
root.mainloop()

當您想停止此過程時,只需調用t.terminate() 閱讀有關多處理模塊文檔的更多信息。

GUI工具箱通常是事件驅動的。 這意味着程序將循環運行以處理事件(鼠標移動,單擊,擊鍵,計時器等)。

通常,可以通過三種方式在事件驅動程序中運行長時間運行的計算。

  • 計時器和回調
  • 分開的過程
  • 線程數

第一種解決方案相對簡單。 您設置了一個計時器。 該計時器用完后將產生一個事件或調用一個回調函數(取決於工具包)。 您在回調中做了一些工作,保存了計算狀態,可能會更新進度指示器,重新啟動計時器並退出回調。 這與GUI很好地融合在一起,但是需要對代碼進行結構化,以便可以將工作分成小塊。 如果回調花費的時間太長,則事件處理將受到影響,GUI將感到無響應。 回調的運行時間不得超過例如10到100毫秒之間。 這種方法無法利用現代CPU中普遍存在的多個內核。

第二種解決方案是開始一個單獨的過程,如mguijarr所示。 在CPython上,這是一個非常好的解決方案,因為您根本不會影響GUI,並且仍然可以使用各種方法(信號,套接字,共享內存,消息隊列)與外部程序進行通信。 這將利用多核的優勢。 使用multiprocessing.Pool您甚至可以在所有可用核心上分配工作。

另一方面,在這種情況下,線程不是CPython中的最佳解決方案。 全局解釋器鎖(“ GIL”)限制了CPython解釋器,以便一次只能有一個線程可以執行Python字節碼。 最初這樣做是為了簡化內存管理。 因此,即使您使用一個單獨的線程進行計算,您仍然可能會餓死處理器時間的GUI並使其無響應。 而且,您必須使用鎖保護多個線程使用的數據。 對於大多數GUI工具包,只有一個線程可以調用工具包函數。 因此,您不能例如從第二個線程更新進度指示器。

我花了幾個小時嘗試使用線程來解決您自己的問題,后來幾個無響應的UI最終導致:TkInter不是線程安全的, 因為tkinter tkMessageBox無法在thread中工作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM