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

the*_*lse 2 python multithreading exception python-2.7

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

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

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

我现在尝试使用属性更改子类并检查主线程中的属性,但我会导致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
Run Code Online (Sandbox Code Playgroud)

这是基本的主线程:

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)
Run Code Online (Sandbox Code Playgroud)

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

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

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

#!/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()
Run Code Online (Sandbox Code Playgroud)

Ste*_*Lin 5

child thread对于 a 来说,控制其并不是最佳实践parent thread。我们通常反其道而行之。

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

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

这里有一篇关于 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()
Run Code Online (Sandbox Code Playgroud)