运行 Python 和 Tornado 的后台任务

Running Background task with Python and Tornado

我已经做了几年的 Web 应用程序开发人员,现在正在研究 Python 和机器人技术。

我已经根据 javascript websocket 命令将 Python Tornado 设置为 运行。 这太棒了,可以移动电机,打开 LED。没问题。

我想做 2 件事。

1) 使 LED 闪烁

2) 使用超声波范围传感器,如果范围 < X

则停止 FORWARD 动作

我自己知道如何做到这两点。

但是,我 python 的方式如下

WS.py

import tornado.httpserver
import tornado.websocket
import tornado.ioloop
import tornado.web
import time
# My Over python module
import tank

class WSHandler(tornado.websocket.WebSocketHandler):

    def open(self):

        print 'New connection was opened'
        self.write_message("Welcome to my websocket!")
        tank.init()

    def on_message(self, message):
        print 'Incoming message:', message
        tank.run(message)
        self.write_message("You said: " + message)

   def on_close(self):
       tank.end()
       print 'Connection was closed...'
   def check_origin(self, origin):
       return True
application = tornado.web.Application([
  (r'/ws', WSHandler),
])

if __name__ == "__main__":
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

TANK.py 将 RPi.GPIO 导入为 gpio 导入时间

def init():
    #Setting up all my pins, Not going to add all

def moveForward():
    #open GPIO pins to move motors forward
def stop():
    # close all GPIO pins to stop motors

def run(action):
    # the method called by the IOLoop
    if action == 'go':
        moveForward()
    elif action == 'stop':
        stop()
    else:
        print "Oops, i cocked up"

注意:tank.py 是摘要而非实际代码。

我的 JS 在鼠标按下时工作,用 go 调用我的 python WS,鼠标向上,调用 stop

正如我所说,工作正常

但是如果我在 moveForward() 方法上添加一个 while 循环来计算范围并在接近时停止,那么我的 WS 将被绑定并且不会监听 STOP

同样,如果我运行一个打开LED、休眠、关闭、休眠的方法,我的WS将无法听取任何命令。

听起来您需要屈服于 IOLoop 以便它可以处理更多输入,同时在 "moveForward" 中继续执行。

如果您需要在 moveForward 的循环之间暂停,请执行以下操作:

@gen.coroutine
def moveForward():
    while True:
        do_something()
        # Allow other processing while we wait 1 sec.
        yield gen.sleep(1)

切勿在 Tornado 回调或协程中使用 "time.sleep",它会阻止整个进程的所有事件处理。请改用 IOLoop.add_timeout 或 "yield gen.sleep(n)"。