在python中的导入类中运行线程

时间:2014-12-19 11:53:10

标签: python multithreading class raspberry-pi

我正在尝试使用覆盆子pi和python的GSM900调制解调器,我正在尝试制作一个简单的库,用于使用ttl串行连接的GSM900 rpi板。

然而,当我导入库(Serialworker.py)并使用我的主python应用程序(sniffer.py)中的serialworker类的start()函数时,我遇到了使线程按预期工作的问题。在start()函数处阻塞并且不继续main.py代码

我有以下主要的python文件:

main.py

#!/usr/bin/python3
from time import sleep
try:
    import RPi.GPIO as GPIO
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(17, GPIO.OUT, initial=0)
except ImportError:
    print("Could not control GPIO\n"
          "Are you root?")
    exit()
from serialworkerpi import serialworker


def powercycle():
    try:
        GPIO.output(17, 0)
        sleep(0.2)
        GPIO.output(17, 1)
    except:
        print("Setup Failed, Are you root?")

def online():
    if not serworker.checkgsm900online():
        print("GSM900 not online, cycling power")
        powercycle()
        while not serworker.checkgsm900online():
            print("Waiting for GSM900")
    else:
        print("GSM900 connection found")

    print("Completed boot cycle")


if __name__ == '__main__':
    """main loop"""
    serworker = serialworker()
    online()
    serworker.start()

    try:
        while serworker.check():
            print("loop")
            sleep(0.5)

    except KeyboardInterrupt:
        serworker.stop()
        print("Shutting down threads")

和这个包含start()函数的库类

Serialworker.py:

class serialworker():
    """This Class instantiates a serial thread and has functions for facilitating communication
    to the serial interface as well as some GSM900 specific functions"""

    def __init__(self, port='/dev/ttyAMA0', baud=115200, timeout=5, pollspeed=0.1):
        """Initialises the variables used in this class, baud=, timeout= and pollspeed= can be adjusted
        But have initial values of 115200, 5 and 0.1 respectively, in the future i could add stopbits and parity here"""

        self.port = port
        self.baud = baud
        self.timeout = timeout
        self.pollspeed = pollspeed
        self.run = False
        self.ser = serial.Serial

        """Command variable description:
        self.command        = Command to write in next while cycle
        self.commandwait    = Bool used to determine if write buffer contains a command for writing in the next while cycle
        self.commandstat    = Variable used to hold the return status of the command that was submitted
        self.commandret     = Bool used to determine if a command was written to the buffer, as to allow the output to be read in the next while cycle
        self.respwait       = Bool used to determine if commandstat is ready to be read
        """
        self.command = ""
        self.commandwait = False
        self.commandstat = ""
        self.commandret = False
        self.respwait = False

    def start(self):
        """Starts a thread of the _readwriteloop() funtion"""
        #TODO add thread checking, only 1 thread per serial interface should be allowed

        self.run = True
        t1 = threading.Thread(target=self.readwriteloop())
        t1.start()
        print("started")

    def checkgsm900online(self):
        """Checks if the GSM900 board is online"""
        gsmser = serial.Serial(
        port=self.port,
        baudrate=self.baud,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS,
        timeout=self.timeout,)
        gsmcheck = ("AT"+"\r\n").encode()
        gsmser.write(gsmcheck)
        sleep(0.03)
        gsmbuffer = gsmser.inWaiting()
        if gsmbuffer == 0:
            gsmser.flush()
            gsmser.close()
            return False
        else:
            gsmser.flush()
            gsmser.close()
            return True

    def check(self):
        """Checks if a thread currently exists"""

        return self.run

    def stop(self):
        """stops running thread"""

        self.run = False

    def inputcommand(self, string, flag):
        """Allows for a single command to be inputted, sets the commandwait to true to tell the loop to check its queue.
        Optionally you can set flag=False to not wait for a return stat on this command"""

        self.command = (string+"\r\n").encode()
        self.commandwait = True
        print("waiting for resp")
        if flag:
            while not self.respwait:
                sleep(0.1)
            self.respwait = False
            return self.commandstat

    def readwriteloop(self):
        """Main function of the class that reads serial data from a buffer
        And checks for new commands inputted by the inputcommand() function
        which output status it will write to the commandstat buffer"""
        #TODO write function for retrieving input command return data not just the status

        ser = self.ser(
        port=self.port,
        baudrate=self.baud,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS,
        timeout=self.timeout,)
        while self.run:
            ser.inWaiting()
            buffer = ser.inWaiting()
            if buffer != 0:
                decodeline = ser.readline().decode('utf-8', "ignore").rstrip('\n')
                if len(decodeline) > 2:
                    if self.commandret:
                        if 'ERROR' in decodeline:
                            self.commandstat = decodeline
                            self.commandret = False
                            self.respwait = True
                        elif 'OK' in decodeline:
                            self.commandstat = decodeline
                            self.commandret = False
                            self.respwait = True
                        elif 'NO CARRIER' in decodeline:
                            self.commandstat = decodeline
                            self.commandret = False
                            self.respwait = True

            if self.commandwait:
                ser.write(self.command)
                #print(self.command)
                self.commandwait = False
                self.commandret = True
            sleep(self.pollspeed)

奇怪的是,当我从Serialworker.py本身运行类时 例如,将此代码附加到文件的末尾:

if __name__ == '__main__':
    x = serialworker()
    x.start()
    i = 0

    while i != 1000:
        i += 1
        x.check()
        sleep(0.01)
    pin = "0000"

    pinconvert = "AT+CPIN=\"%s\"" % pin
    succeed = x.inputcommand(pinconvert, True)
    print(succeed)

    while i != 10000:
        i += 1
        x.check()
        sleep(0.01)

    x.stop()
    isonline = x.checkgsm900online()
    print(isonline)

它按预期工作,只要while循环继续运行,start()函数就不会阻塞和运行

1 个答案:

答案 0 :(得分:0)

问题在于你正在调用一个应由线程执行的函数:

Thread(target=self.readwriteloop())

应该是

Thread(target=self.readwriteloop)