簡體   English   中英

線程與 Python

[英]Threading with Python

完成 python 新手...我正在使用 Arduino pyfirmata package,我正在嘗試做一些非常簡單的事情。

根據對 python 的用戶輸入,我是否想要一個 LED 到 flash。

我的問題是 python 程序只要求用戶輸入一次,但我希望它始終要求輸入,以便用戶可以隨時更改 function。

我試過使用線程 package 但沒有成功......也許有更簡單的方法,但我對編碼完全陌生,所以我不知道任何其他方法。 接受建議!

這是我的代碼,

import pyfirmata
import threading
import time

board = pyfirmata.Arduino('/dev/cu.usbmodem14101')

def flash():
    for i in range(1000):
        board.digital[13].write(1)
        time.sleep(1)
        board.digital[13].write(0)
        time.sleep(1)

def stop():
    board.digital[13].write(0)


while True:
    runMode = input("Run or Stop? ")

    if runMode == "Run":
        x = threading.Thread(target=flash(), args=(1,))
        x.start()
        # x.join()

    elif runMode == "Stop":
        x = threading.Thread(target=stop(), args=(1,))
        x.start()
        #x.join()

如果你只想殺死線程,你可以使用 mulitiprocessing,其中 multiprocessing.Process 可以 p.terminate()

p = Process(target=flash, args=(,))
while True:
    runMode = input("Run or Stop? ")
    if runMode == "Run":
        p.start()
    elif runMode == "Stop":
        p.terminate()

但是,不建議只終止線程,因為如果進程正在處理關鍵資源或依賴於其他線程,它可能會導致錯誤,請參閱此處以獲得更好的解釋有沒有辦法終止線程?

此處描述的一個更好的選擇是使用標志來處理您的閃爍,它們允許線程之間進行簡單的通信

from threading import Event

e = event()

def check_for_stop(e):
    while not e.isSet():
         flash()
    print("Flashing Ended")

while True:
    runMode = input("Run or Stop? ")

    if runMode == "Run":
        x = threading.Thread(target=check_for_stop, args=(e,))
        x.start()
        # x.join()

    elif runMode == "Stop":
        e.set() #set flag true
        e.clear() #reset flag

這是有關事件對象的更多信息的文檔https://docs.python.org/2.0/lib/event-objects.html

我還沒有測試過這段代碼只是一個例子,如果它不能立即工作,我深表歉意

編輯:只要再次查看您的 function,您就會想在閃爍期間檢查標志,這是我的錯誤道歉,所以您的 flash function 看起來像

def flash():
    while e.isSet():
        board.digital[13].write(1)
        time.sleep(1)
        board.digital[13].write(0)
        time.sleep(1)

你會像以前一樣將它傳遞到線程中

x = threading.Thread(target=flash(), args=(1,))
x.start()

您在代碼中遇到錯誤。

您應該通過以下方式創建線程:

x = threading.Thread(target=flash)

注意:您輸入了“flash()”,因此在主線程中執行該方法。 而且你的方法沒有任何 arguments 因此你可以刪除 args 值

您可以通過創建自己的Thread子類(例如下面的Flasher class)以面向對象的方式來完成此操作。

這種方法的優點之一是可以相對容易地擴展Flasher class 並使其控制連接到不同輸出的 LED,或者允許在創建時指定閃光之間的延遲。 執行前者將允許多個實例同時運行。

import pyfirmata
import threading
import time

OFF, ON = False, True

class Flasher(threading.Thread):
    DELAY = 1

    def __init__(self):
        super().__init__()
        self.daemon = True
        self.board = pyfirmata.Arduino('/dev/cu.usbmodem14101')
        self.flashing = False
        self.LED_state = OFF

    def turn_LED_on(self):
        self.board.digital[13].write(1)
        self.LED_state = ON

    def turn_LED_off(self):
        self.board.digital[13].write(0)
        self.LED_state = OFF

    def run(self):
        while True:
            if self.flashing:
                if self.LED_state == ON:
                    self.turn_LED_off()
                else:
                    self.turn_LED_on()
            time.sleep(self.DELAY)

    def start_flashing(self):
        if self.LED_state == OFF:
            self.turn_LED_on()
        self.flashing = True

    def stop_flashing(self):
        if self.LED_state == ON:
            self.turn_LED_off()
        self.flashing = False


flasher = Flasher()
flasher.start()

while True:
    runMode = input("Run or Stop? ").strip().lower()

    if runMode == "run":
        flasher.start_flashing()
    elif runMode == "stop":
        flasher.stop_flashing()
    else:
        print('Unknown response ignored')

暫無
暫無

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

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