有一些方法可以盗版 Flask,但不推荐。简而言之,Flask 对多线程没有很好的支持,并行执行是您的解决方案所需的要求之一(假设您计划以“更多”标准方式执行此操作)。
正如我在 cmets Flask 中提到的那样,仅凭自己无法完成您想做的事情。这是因为在典型的HTTP/1.1 事务(您的浏览器和 Flask 用于通信的协议)中不支持双向数据流。换句话说:当客户端向服务器发送请求时,Flask 将响应呈现的 HTML 页面,然后关闭连接。您需要让服务器保持与客户端的连接,并向客户端发送对textfile.txt 的任何更新。
要实现这一点,您需要在客户端和服务器端使用另一个协议,以及在服务器端使用异步代码执行。
关于协议,这类事情的标准是Websocket。关于异步代码执行,这是 Flask 的一个问题:这个问题的要求之一是服务器需要 (1) 跟踪文本文件,以及 (2) 在更新时向客户端发送文本文件.用 Flask 做到这一点需要一些多线程,这对 Flask 不是很友好。因此,我实际上建议您研究类似FastAPI 的东西,它带有开箱即用的内置 Websocket,并且可以异步运行。
我还应该提到,您面临的问题相当独特,而且我个人从未见过适用的问题。我无法确认,但这看起来确实像 XY problem。
例如,这里有一些代码可以使用 Flask、Flask-SocketIO (pip install flask-socketio) 和多线程来完成您正在寻找的工作。
请注意,Socket.IO 构建在 websocket 之上,并且客户端和服务器端都需要自己的支持代码。我不会详细说明为什么一个而不是另一个,但只需了解香草 Websocket 和 Socket.IO 在使用、应用程序等方面存在显着差异。另请注意,将threading 与 Flask 一起使用会导致必须处理的令人讨厌的未定义行为。自动重新加载之类的东西会中断并迫使您不断地重新加载应用程序。
再次:我无法充分表达我对 FastAPI 更好地解决这个问题的感觉(由于异步代码执行的能力),但为了直接回答您的问题,这里使用 Flask 实现了一个低于标准的实现:
from flask import Flask, render_template
from flask_socketio import SocketIO
from threading import Thread
from time import sleep
app = Flask(__name__)
io = SocketIO(app)
@app.route("/")
def index():
return render_template("texts.html", content=get_file())
def get_file(loop=False, io=None):
text = open("textfile.txt", "rb")
def read():
data = text.read()
text.seek(0)
return data
old = read()
while loop:
current = read()
if current != old:
io.emit("text", read().decode("utf-8"), broadcast=True)
old = current
sleep(1)
return text.read().decode("utf-8")
if __name__ == "__main__":
Thread(target=lambda: get_file(loop=True, io=io)).start()
io.run(app, debug=True)
在客户端你需要有:
<html>
<head>
<style>
.textzone {
overflow: scroll;
border: 3px solid #009688;
width: 330px;
background-color: rgb(231, 226, 226);
height: 330px;
position: relative;
left: 125px;
top: 80px;
-webkit-box-shadow: 11px 11px 10px 2px #262626;
box-shadow: 11px 11px 10px 2px #262626;
padding: 20px;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
<script type="text/javascript" charset="utf-8">
console.log("running.");
const socket = io('http://127.0.0.1:5000')
socket.on('text', function(msg) {
document.getElementById("content").innerHTML = msg;
});
</script>
</head>
<body>
<div class="textzone">
<pre id="content">{{ content }}</pre>
</div>
</body>
</html>