从 Python child 线程接收数据的简单方法

Easy way to receive data from Python child thread

我正在开发一个简单的 python 脚本,该脚本将串行通信命令发送到 Arduino。 我有一个 main-thread 发送命令,然后另一个 child-thread 等待用户输入。

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

我想这样做的方法是从 child 线程抛出 异常 并在主线程中捕获它们,但我很快意识到我是完全不可能,因为每个线程都在自己的上下文中运行,并且 child 线程无法向主线程发送异常。

我现在正尝试用属性更改 child class 并检查主线程中的属性,但我会在主线程中导致很多令人困惑的 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)

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

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

EDIT(以下代码已经过测试) 以下代码的问题在于,如果事件花费无限时间,则无法停止 child 进程。 运行 示例并写入 "start"... 然后 child 开始工作,然后如果您发送另一个事件 "such as stop" 它将被忽略。

#!/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()

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

在您的情况下,您可以将用户输入放在主线程中,而将您的工作放在子线程中。 Python中线程之间的通信通常是通过Event和signal来完成的。如果您表现出兴趣,可以google。

这是您的案例的示例。希望能帮助到你。我简化了 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()