我正在尝试使用Flask做某种状态机。当我的应用启动时,我启动一个后台任务,该任务以“ state_0()”函数开头,并依次跳转到其他函数“ state_1()”,然后依次跳转到“ state_2()”,然后返回到“ state_0()”。
此s0-> s1-> s2-> s0-> s1-> ...从一开始就一直在运行Web应用程序,并且我想做的事情一直是“ socketio.emit('refresh' ,状态)”,以便可以相应地更新FrontEnd。
为此,我使用了一个带有@ app.before_first_request的线程,该线程基本上是使用应用程序上下文运行“ state_0()”的。
问题是发射仅适用于state_0()函数。
我当前的代码可以简化如下:
myapp.py
nums=re.findall('[0-8]+',updatedStr)
myindex.html
from flask import Flask, render_template, current_app
from flask_socketio import SocketIO, emit
import threading
import time, json
DATA = {'state': '0'}
N = 5 # Fake pooling
# initialize Flask
app = Flask(__name__)
socketio = SocketIO(app)
def state_0():
# Update DATA
global DATA
DATA['state'] = '0'
socketio.emit('refresh', json.dumps(DATA), broadcast=True)
print("State " + DATA['state'] + "!")
# Dummy pooling simulation
i = 0
while i < N:
print("Dummy workload " + DATA['state'] + "...")
time.sleep(3)
i += 1
state_1()
def state_1():
# Update DATA
global DATA
DATA['state'] = '1'
socketio.emit('refresh', json.dumps(DATA), broadcast=True)
print("State " + DATA['state'] + "!")
# Dummy pooling simulation
i = 0
while i < N:
print("Dummy workload " + DATA['state'] + "...")
time.sleep(3)
i += 1
print("Alarm(s) detected!")
state_2()
def state_2():
# Update DATA
global DATA
DATA['state'] = '2'
socketio.emit('refresh', json.dumps(DATA), broadcast=True)
print("State " + DATA['state'] + "!")
# Dummy pooling simulation
i = 0
while i < N:
print("Dummy workload " + DATA['state'] + "...")
time.sleep(3)
i += 1
state_0()
@app.before_first_request
def activate_job():
def run_job():
with app.app_context():
state_0()
thread = threading.Thread(target=run_job)
thread.start()
@app.route('/')
def index():
return render_template('myindex.html')
# Every time Client refresh the web, we broadcast the current DATA
@socketio.on('connect')
def on_connect():
print("[Server.on_connect]: A new connection!")
emit('refresh', json.dumps(DATA), broadcast=True)
if __name__ == '__main__':
socketio.run(app, debug=True)
我也尝试这样做:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>State Machine</title>
</head>
<body>
<p>State machine...</p>
<form action="">
<input id ="s0" type="radio" name="state0"> State 0<br>
<input id ="s1" type="radio" name="state1"> State 1<br>
<input id ="s2" type="radio" name="state2"> State 2<br>
</form>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
<script type="text/javascript" charset="utf-8">
var socket = io.connect('http://' + document.domain + ':' + location.port);
// verify our websocket connection is established
socket.on('connect', function () {
console.log('Websocket connected!');
});
socket.on('refresh', function (DATA) {
var DATA = JSON.parse(DATA);
console.log('[refresh] Frontend has updated info! Now we are in state ' + DATA.state);
console.log('[refresh] All variables are:');
console.log(DATA);
switch (DATA.state) {
case '0':
document.getElementById('s2').checked = ""
document.getElementById('s0').checked = "checked"
break;
case '1':
document.getElementById('s0').checked = ""
document.getElementById('s1').checked = "checked"
break;
case '2':
document.getElementById('s1').checked = ""
document.getElementById('s2').checked = "checked"
break;
default:
// code block
}
});
</script>
</body>
</html>
我曾在各处尝试过与app.app_context()一起使用,但仅与state_0()函数一起使用。
我希望我的问题清楚。请注意,我想使事情尽可能简单(这就是为什么我使用全局变量来保持状态,以及为什么不使用Celery运行后台任务的原因)。这不是用于生产。
希望有人可以提供帮助!
注意:要在ubuntu中测试此示例,请创建一个“ virtualenv env”,然后“ pip3 install flask flask-socketio eventlet”并运行“ python3 myapp.py”