Python 将后台日志实时同步到前端

原创
2018/08/05 20:17
阅读数 9.3K

Python 将后台日志实时同步到前端

针对这个需求,网上有说后台生成文件,前端用 ajax 来 fetch ,不过我没有试过。我是尝试 websocket 来实现,参考了http://www.cnblogs.com/hhh5460/p/7397006.html/

  1. 一次失败的尝试
    • tornado 实现网站,并且用 tornado 原生支持的 websocket实现推送;
      1. tornado 实现网站
      2. tornado 实现 websocketHandler,在里边重写 open 函数,在open函数里边一个死循环监听队列,队列有信心就输出队列信息
      3. 前端页面加载的时候建立连接。
    • 这样倒是能把已经放在队列的信息输出,但是输出之后一直在那个循环,tornado是基于 epoll 的单线程模型实现,导致其他请求都无法进入。
  2. Flask + Flask socketIO + 全局队列
    • Flask 实现网站接口,这里不多说
    • Flask socketIO 实现websocket
      from threading import Lock
      from flask import Flask, render_template, request
      from flask_socketio import SocketIO
      from Service import nlu_test
      import logF
      
      async_mode = None
      app = Flask(__name__)
      app.config['SECRET_KEY'] = 'secret!'
      socketio = SocketIO(app, async_mode=async_mode)
      
      thread = None
      thread_lock = Lock()
      
      
      # Get data from queue and push to front
      def background_thread():
          while True:
              if logF.not_empty:
                  socketio.emit('server_response', logF.pop(), namespace='/log')
      
      
      @app.route('/')
      def index():
          return render_template('search.html', async_mode=socketio.async_mode)
      
      
      @app.route('/query', methods=['POST'])
      def query():
          if request.method == 'POST':
              query = request.form.get('query', '')
              return nlu_test(query)
      
      
      @socketio.on('connect', namespace='/log')
      def log():
          global thread
          with thread_lock:
              if thread is None:
                  thread = socketio.start_background_task(target=background_thread)
      
      
      if __name__ == '__main__':
          socketio.run(app, debug=True)
      
    • 前端 websocket 连接
      $(document).ready(function () {
          namespace = '/log';
          var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + namespace);
          socket.on('server_response', function (res) {
              var logNode = document.createElement("p");
              logNode.innerText = res;
              oShowLog.appendChild(logNode);
              oShowLog.scrollTop = oShowLog.scrollHeight;
          });
      });
      
    • Python 跨模块的全局变量
      • 以上步骤都是参考网上实例修改,我的需求是在后台的任何地方,调用一个函数log("hello world") 就能将信息同步到前端,因此我尝试使用一个全局变量。
      • Global 定义的全局变量只能在 module 内部,也就是一个 py 文件内;
      • 一个module是在哪里都可以引用的,模块内的 Global 变量又是 module全局可用的,只要在使用的文件里边引用 module 就可以跨模块了。
        from queue import Queue
        
        global _log_queue
        _log_queue = Queue(10)
        
        def log(str_log):
            _log_queue.put(str_log)
        
        def pop():
            res = _log_queue.get()
            _log_queue.task_done()
            return res
        
        def not_empty():
            return _log_queue.not_empty
        

wbq813的个人博客http://codeyourlife.cn

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部