线程瓶子应用程序

2024-04-20 06:41:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个简单的瓶子脚本,转发网页上的按钮进程。在同一个脚本中,我希望有一个连续的循环,在其他任务中,可以监听这些按钮的按下。我试图在一个单独的线程中运行瓶子脚本,但它没有按我的预期工作。

有更好的(或者说我应该说正确的)方法来做这个吗?

from bottle import get, post, request, run, redirect
import threading

@get('/button')
def button():
    return '''
        <form action="/button" method="post">
            <input type="submit" value="Push" />
        </form>
    '''

@post('/button')
def action():
    print "button pushed"
    pushed = True
    redirect("/button")

#run(host='localhost', port=8080)
threading.Thread(target=run, kwargs=dict(host='localhost', port=8080)).start()


def method():
    pushed = False
    print "started"
    while 1:
        # do other stuff
        if pushed:
            print "push recieved"
            pushed = False

method()

Tags: runimportform脚本瓶子getdefbutton
1条回答
网友
1楼 · 发布于 2024-04-20 06:41:39

它不起作用,因为它只看到在method内部定义的局部变量pushed,而不是全局可见且可修改的pushed变量。

您需要的是以下内容(但向下滚动以获得正确的解决方案):

pushed = False

@post('/button')
def action():
    global pushed  # needed because otherwise assigning to `pushed` will
                   # just create a local variable shadowing the global one
    pushed = True
    redirect("/button")

def method():
    # pushed = False   <----- this line is not needed, and if enabled, will, again, 
    #                         create a local variable shadowing the global one
    global pushed  # again, otherwise the `pushed = False` statement will create a local variable
    while True:  # use real booleans, i.e. True/False not 1/0
        if pushed:
            print "push recieved"
            pushed = False

method()

注意:注意我在代码片段中添加的注释。

但是,通过全局变量(或普通变量)与线程通信是不好的做法,因为多个其他线程可能同时访问(读或写)同一个变量。相反,要在线程之间发送事件信号,请使用队列:

from Queue import Queue, Empty

button_pressed = Queue()

@post('/button')
def action():
    button_pressed.put(1)  # can be any value really
    redirect("/button")

def method():
    while True:
        try:
            button_pressed.get_nowait()
        except Empty:
            # NOTE: if you don't do anything here, this thread
            # will consume a single CPU core
            pass
        else:
            print "push recieved"

get_nowait()检查队列中是否有东西已被put,如果是,则返回它;否则它将立即引发Empty。您还可以将非零超时传递给它,或者在没有超时的情况下调用它,在这种情况下,它将等待队列中有可用的内容。

最好使用带超时的.get(),而不是nowait版本,这样线程就不会毫无用处地消耗CPU。

此外,不应将诸如启动线程的行以及调用method()的行之类的代码直接放入模块的顶级作用域;相反,应按如下方式有条件地调用它们:

if __name__ == '__main__':
    threading.Thread(target=run, kwargs=dict(host='localhost', port=8080)).start()
    method()

这样,代码只在直接执行.py文件时执行,而不是作为模块导入时执行。另外,考虑正常调用run(),而不是将method放入线程中。

相关问题 更多 >