Запустите цикл while как фоновый процесс в приложении Flask - PullRequest
0 голосов
/ 20 июня 2019

Я хочу запустить веб-сервер, который читает поток на 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 голосов
/ 20 июня 2019

Попробуйте поискать что-то вроде 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()
0 голосов
/ 20 июня 2019

Я закончил тем, что сделал следующее:

У меня есть маленький файл publisher.py, который читает данные с порта на указанном хосте (хотя он мог бы с таким же успехом читать из sys.stdin, используя приведенный выше код)в то время как цикл.Когда он составляет frame, он публикует этот кадр в хранилище данных Redis.

Затем, внутри моего слушателя маршрута Flask /frame, я просто пингую хранилище данных Redis и затем 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)
0 голосов
/ 20 июня 2019

Вы можете попробовать запустить его в потоке

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

для функции потока, определите в ней цикл while

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...