在Flask应用中将while循环作为后台进程运行

时间:2019-06-19 21:17:02

标签: python flask process

我正在寻找一个运行网络服务器,该服务器读取sys.stdin上的流。该读取需要连续发生,例如在while循环中。

但是,我还希望运行一个Flask服务器,该服务器侦听对/data的请求,并将从sys.stdin读取的最后数据发送给请求的代理。

到目前为止,我发现我的while循环正在中止我的应用程序的执行,这绝对有道理。这是我的设置:

from flask import Flask, jsonify
import sys

# state
frames = []
frame = []

while True:
  l = sys.stdin.readline()
  if 'end_frame' in l:
    frames = [frame] + frames
    frame = []
  elif l.rstrip('\n'):
    frame.append(l.rstrip('\n'))

# app
app = Flask(__name__, static_url_path='')

@app.route('/frames')
def get_frames():
  return jsonify(frames)

app.run(host='0.0.0.0', port=5050)

是否有一种方法可以将while循环作为后台进程运行,以释放烧瓶路由侦听器?任何建议都会有所帮助!

3 个答案:

答案 0 :(得分:0)

您可以尝试在线程中运行它

import threading
x = threading.Thread(target=thread_function, args=(index,))
threads.append(x)
x.start()

对于线程函数,在其中定义您的while循环

答案 1 :(得分:0)

尝试调查BackgroundScheduler之类的内容。它在后台将任务作为单独的线程运行,而不会暂停烧瓶侦听器。

from apscheduler.schedulers.background import BackgroundScheduler
...
...
def readlines():
  l = sys.stdin.readline()
  if 'end_frame' in l:
    frames = [frame] + frames
    frame = []
  elif l.rstrip('\n'):
    frame.append(l.rstrip('\n'))

with app.app_context():
    scheduler = BackgroundScheduler()
    scheduler.add_job(readlines, 'interval', seconds=10)
    scheduler.start()

答案 2 :(得分:0)

我最终做了以下事情:

我有一个小文件publisher.py,它在while循环中从给定主机上的端口读取(尽管也可以使用上面的代码从sys.stdin中读取)。当它组成frame时,会将其发布到redis数据存储中。

然后,在我的Flask路由侦听器/frame内,我只对redis数据存储执行ping操作,然后jsonify进行结果。通过这种方式,我的发布者和服务器一起工作,以将数据提供给客户端……

publisher.py

import sys, socket, redis, json

# config
stream = {'host': '127.0.0.1', 'port': 6000} # streaming data host / port
r = redis.Redis(host='127.0.0.1', port=6379) # redis instance host / port

# consume data from a host+port and publish to redis on localhost
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((socket.gethostbyname(stream['host']), stream['port'])) # host, port

# consume data
frame = [] # initialize the container obj that will hold all frame data
while True:
  data = client.recv(1024).decode('utf8')
  for l in data.split('\n'):
    if 'end_frame' in l:
      d = {i.split(':')[0]: i.split(':')[1] for i in frame if ':' in i}
      r.set('frame', json.dumps(d))
      frame = []
      print(' * published frame', d.get('frame_number', ''))
    elif l.rstrip('\n'):
      frame.append(l.rstrip('\n'))

server.py

from flask import Flask, jsonify
import redis, sys, os, json

# app
app = Flask(__name__, static_url_path='')

# redis
r = redis.Redis(host='127.0.0.1', port=6379) # redis instance host / port

# route listeners
@app.route('/api/frame')
def get_frame():
  frame = json.loads(r.get('frame').decode('utf8'))
  return jsonify(frame)

if __name__ == '__main__':
  app.run(host='0.0.0.0', port=5050)