从Python子线程接收数据的简便方法

时间:2015-01-09 07:47:15

标签: python multithreading python-2.7 exception

我正在研究一个简单的python脚本,它将串行通信命令发送到 Arduino 。 我有一个发送命令的主线程,然后是另一个等待用户输入的子线程

这应该很简单,但我希望这个过程非常快。 例如,如果用户输入"停止",我想立即停止主线程

我想这样做的方法是从子线程中抛出 exceptions 并捕获主线程中的那些,但我很快意识到我很不可能,因为每个线程都是自己运行的context和子线程无法向主线程发送异常。

我现在正在尝试使用属性更改子类并检查主线程中的属性但是我会在主线程中导致许多令人困惑的if-statements并且它也不是一个好的解决方案,因为它确实如此不要立即停止执行。

class User_input_thread (threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.isPauseRequested = False
        self.isStopRequested = False
    def run(self):
        while (True):
            s = raw_input(">")
            if s.startswith("pause"):
                self.isPauseRequested = True
            elif s.startswith("start"):
                self.isPauseRequested = False
            elif s.startswith("stop"):
                self.isStopRequested = True

这是基本的主线:

def start_demo():
    user_input_thread = User_input_thread()  
    user_input_thread.start()


    while (True):
        if (not user_input_thread.isPauseRequested):
            # DO SOME WORK HERE
            time.sleep(10)
        if (not user_input_thread.isStopRequested):
            # DO SOME WORK HERE
            time.sleep(10)

实现我想要的行为的简单方法是什么?

请不要链接到讨论线程之间异常的其他网页。至少解释我应该如何使用代码或修改我的代码,以便我能理解。

编辑 (以下代码已经过测试) 以下代码的问题是,如果事件占用无限时间,则无法停止子进程。 运行示例并编写"开始" ....然后孩子开始工作,然后如果你发送另一个事件"例如停止"它将被忽略。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import threading
import time

class child_thread(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.stop_request = threading.Event()
        self.start_request = threading.Event()
        self.pause_request = threading.Event()

    def run(self):
        while 1:
            if self.stop_request.isSet():
                print 'stop request is set!!'
                self.stop_request.clear()
                while 1:
                    print "stop running..."
                    time.sleep(1)
            if self.pause_request.isSet():
                print 'pause request is set!!'
                self.pause_request.clear()
                while 1:
                    print "pause running..."
                    time.sleep(1)
            if self.start_request.isSet():
                print 'start request is set!!!'
                self.start_request.clear()
                while 1:
                    print "start running..."
                    time.sleep(1)

    def show(self, event='stop'):
        if event == 'stop':
            self.stop_request.set()
        elif event == 'start':
            self.start_request.set()
        elif event == 'pause':
            self.pause_request.set()
        elif event == 'exit':
            print 'enter exit'
            self.join(1)


def main_thread():

    t1 = child_thread()
    t1.start()

    while 1:
        s = raw_input(">")
        t1.show(event=s)
        if s == 'exit':
            break

    print 'Done! child thread has been killed'

main_thread()

1 个答案:

答案 0 :(得分:3)

child thread控制其parent thread并非最佳做法。我们通常会做相反的事情。

在您的情况下,您可以将用户输入放在主线程中,并将您的工作放在子线程中。  Python中线程之间的通信通常由Event和signal完成。如果你表现出兴趣,你可以谷歌这个。

以下是您案例的示例。希望能帮助到你。我简化了if条件,这不是关键点。 :)

#!/usr/bin/python
# -*- coding: utf-8 -*-

import threading
import time


class child_thread(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.stop_request = threading.Event()
        self.start_request = threading.Event()
        self.pause_request = threading.Event()

    def run(self):
        while 1:
            if self.stop_request.isSet():
                print 'stop request is set!!'
                break
            if self.pause_request.isSet():
                print 'pause request is set!!'
                break
            if self.start_request.isSet():
                print 'start request is set!!!'
                break
            print 'no stop/pause/start is set!!'
            time.sleep(1)

    def join(self, timeout=None, event='stop'):
        if event == 'stop':
            self.stop_request.set()
        elif event == 'start':
            self.start_request.set()
        elif event == 'pause':
            self.pause_request.set()

        super(child_thread, self).join(timeout)

def main_thread():

    t1 = child_thread()
    t1.start()

    while 1:
        s = raw_input(">")
        t1.join(event=s)
        break
    print 'Done! chile thread has been killed'

main_thread()

这是一篇非常好的文章,用于Python中的线程之间的通信。 http://eli.thegreenplace.net/2011/12/27/python-threads-communication-and-stopping

编辑:

以下是您更新的请求的代码。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import threading
import time


class child_thread(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.stop_request = threading.Event()
        self.start_request = threading.Event()
        self.pause_request = threading.Event()

    def run(self):
        while 1:
            if self.stop_request.isSet():
                print 'stop request is set!!'
                self.stop_request.clear()
                continue
            if self.pause_request.isSet():
                print 'pause request is set!!'
                self.pause_request.clear()
                continue
            if self.start_request.isSet():
                print 'start request is set!!!'
                self.start_request.clear()
                continue

    def show(self, event='stop'):
        if event == 'stop':
            self.stop_request.set()
        elif event == 'start':
            self.start_request.set()
        elif event == 'pause':
            self.pause_request.set()
        elif event == 'exit':
            print 'enter exit'
            self.join(1)


def main_thread():

    t1 = child_thread()
    t1.start()

    while 1:
        s = raw_input("\n>enter exit to exit:")
        t1.show(event=s)
        if s == 'exit':
            break

    print 'Done! chile thread has been killed'

main_thread()