从 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()
我正在开发一个简单的 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()