(Python)使用原始输入停止线程?

时间:2016-09-15 00:27:58

标签: python multithreading

编辑9/15/16:在我的原始代码中(仍在下面发布)我尝试将.join()与函数一起使用,这是一个愚蠢的错误,因为它只能用于用线程对象。我在尝试着 (1)连续运行获取数据并将其保存到文件的线程 (2)具有第二个线程或合并队列,一旦用户输入标志(即“停止”),它将停止程序。它不会中断数据收集/保存线程。

我需要多线程帮助。我正在尝试运行两个线程,一个处理数据,另一个检查一个标志来停止程序。

我通过反复试验了解到,如果没有计算机爆炸,我就无法中断while循环。另外,我放弃了我的GUI代码,因为它使我的代码太复杂了多线程。

我想要做的是运行一个从Arduino收集数据的线程,将其保存到文件中,并重复此操作。第二个线程将扫描标志 - 可以是raw_input?我想不出用户可以做什么来阻止数据采集程序。

我非常感谢任何帮助。这是我的代码(大部分都是伪代码,如你所见):

#threading
import thread
import time

global flag

def monitorData():
    print "running!"
    time.sleep(5)

def stopdata(flag ):

    flag = raw_input("enter stop: ")

    if flag == "stop":
        monitorData.join()

flag = "start"

thread.start_new_thread( monitorData,())
thread.start_new_thread( stopdata,(flag,))

当我尝试在IDLE中输入“stop”时,我得到的错误就是这个。

线程中未处理的异常 Traceback(最近一次调用最后一次):   文件“c:\ users \ otangu~1 \ appdata \ local \ temp \ _IDLE_rtmp_h_frd5”,第16行,在stopdata中 AttributeError:'function'对象没有属性'join'

我再一次非常感谢任何帮助,到目前为止,我已经自学了Python,这是我遇到的第一个巨大的墙。

3 个答案:

答案 0 :(得分:1)

你正在寻找这样的事情:

from threading import Thread
from time import sleep

# "volatile" global shared by threads
active = True

def get_data():
    while active:
        print "working!"
        sleep(3)

def wait_on_user():
    global active
    raw_input("press enter to stop")
    active = False        

th1 = Thread(target=get_data)
th1.start()
th2 = Thread(target=wait_on_user)
th2.start()

th1.join()
th2.join()

您在代码中犯了一些明显的错误和一些不太明显的错误。首先,在线程对象上调用join,而不是函数。同样,join不会杀死一个线程,它等待线程完成。当没有更多代码要执行时,线程结束。如果你想要一个线程运行直到设置了一个标志,你通常会在你的线程中包含一个循环,每隔一秒左右检查一次标志(取决于你需要多长时间的精确度)。

此外,螺纹模块优于下杠杆螺纹模块。后者已在python3中删除。

答案 1 :(得分:1)

您看到的错误是在函数上调用join的结果。您需要在join对象上调用thread。您没有捕获对该线程的引用,因此无论如何您都无法调用join。你应该join这样。

th1 = thread.start_new_thread( monitorData,())

# later
th1.join()

对于解决方案,您可以使用Queue在线程之间进行通信。该队列用于向工作线程发送退出消息,如果工作者没有从队列中选择任何东西一秒钟,它会运行从arduino收集数据的代码。

from threading import Thread
from Queue import Queue, Empty


def worker(q):
    while True:

        try:
            item = q.get(block=True, timeout=1)

            q.task_done()
            if item == "quit":
                print("got quit msg in thread")
                break

        except Empty:
            print("empty, do some arduino stuff")


def input_process(q):
    while True:
        x = raw_input("")

        if x == 'q':
            print("will quit")
            q.put("quit")
            break

q = Queue()
t = Thread(target=worker, args=(q,))
t.start()

t2 = Thread(target=input_process, args=(q,))
t2.start()

# waits for the `task_done` function to be called
q.join()

t2.join()
t.join()

它可能比您希望的代码多一些,并且必须检测队列是空的,异常有点难看,但这不依赖于任何全局变量,并且总是会立即退出。基于sleep的解决方案不会出现这种情况,它需要在恢复执行之前等待对sleep的任何当前调用完成。

正如其他人所说,你应该使用threading而不是旧的thread模块,我建议你学习python 3而不是python 2.

答案 2 :(得分:0)

这是不可能的。线程功能必须完成。你不能从外面加入它。