Я удалил большую часть своего кода, чтобы Я могу включить его ниже:
Код: Выделить всё
import datetime as dt
import threading
from os import getenv
import boto3
from awswrangler.timestream import query
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler
from bokeh.client.session import pull_session
from bokeh.embed import server_session
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.server.server import Server
from bokeh.util.token import generate_session_id
from dotenv import load_dotenv
from tornado.ioloop import IOLoop
from flask import Flask, render_template, request, jsonify
class DataViewer:
def make_doc(self, doc):
self.df = None
self.source = ColumnDataSource(data={"x": [], "y": []}, name="source")
self.p = figure(
name="p",
title="Level",
sizing_mode="stretch_width",
height=500,
x_axis_type="datetime",
y_range=(0, 1),
output_backend="webgl",
)
self.renderer = self.p.line(x="x", y="y", source=self.source, color="navy")
self.layout = self.p
doc.add_root(self.layout)
self.doc = doc
return self.doc
def prepare_view(self):
self.source.data = dict(
x=list(viewer.df["time"].apply(
lambda x: x.replace(tzinfo=dt.timezone.utc).timestamp() * 1000)
),
y=list(viewer.df["measure_value::double"]),
)
self.p.x_range.start = self.source.data['x'][0]
self.p.x_range.end = self.source.data['x'][-1]
self.p.y_range.start = max(self.source.data['y']) * 1.09
self.p.y_range.end = min(self.source.data['y']) * 1.09
def start_server(self, port=5000):
bokeh_app = Application(FunctionHandler(self.make_doc))
server = Server(
{"/bkapp": bokeh_app},
port=port,
io_loop=IOLoop(),
allow_websocket_origin=["*"],
)
server.start()
server.io_loop.start()
load_dotenv()
boto3.setup_default_session(profile_name=getenv("PROFILE"))
app = Flask(__name__)
@app.route("/")
def dataviewer():
with pull_session(
session_id=generate_session_id(), url=f"http://localhost:5006/bkapp"
) as session:
script = server_session(
session_id=session.id, url=f"http://localhost:5006/bkapp"
)
return render_template("base.html", script=script)
@app.route("/search", methods=["POST"])
def search():
print(request.form["imei"])
try:
viewer.df = query(
f"""
SELECT time, measure_value::double FROM DeviceData."RawData"
WHERE measure_name = 'WaterDepth' AND Imei = '{request.form['imei']}'
ORDER BY 1 ASC
"""
)
except Exception as e:
print("get_data error", e)
return (
"error getting data",
500,
)
if len(viewer.df) == 0:
print("No data found")
viewer.doc.add_next_tick_callback(viewer.prepare_view)
return jsonify(viewer.source.data)
def bk_worker():
global viewer
viewer = DataViewer()
viewer.start_server(port=5006)
threading.Thread(target=bk_worker).start()
app.run(port=5000)
Код: Выделить всё
Data Viewer
Search
{{ script|safe }}
$(document).ready(function () {
imei = 0;
$('#search').submit(function (e) {
e.preventDefault();
if (imei == $('#search input[name="imei"]').val()) {
return;
}
$("#loading-spinner").show();
imei = $('#search input[name="imei"]').val();
$.ajax({
url: 'search',
method: 'POST',
data: {
imei: imei
}
}).done(function (response) {
let ds = Bokeh.documents[0].get_model_by_name('source');
ds.data['x'] = response['x']; ds.data['y'] = response['y'];
ds.change.emit();
$("#loading-spinner").hide();
})
});
});
Моя проблема в том, что если я у меня есть два экземпляра этого приложения на разных вкладках, они каким-то образом связаны. При быстром последовательном поиске по каждому экземпляру правильно обновится только один экземпляр. Похоже, что экземпляр, который работает неправильно, получает некоторые данные, но тот, который обновляется, получает набор данных для каждого поиска. Вот видео, демонстрирующее это:
У меня также была аналогичная проблема с обратными вызовами, которые у меня были. написанные, которые я пропустил в приведенном выше коде, поскольку считаю, что основная проблема не имеет к ним никакого отношения.
Я пытался найти способы разделения экземпляров, а именно pull_session и использование идентификаторов сеансов, но Кажется, я просто не могу заставить это работать.
Буду признателен за любую помощь!
Подробнее здесь: https://stackoverflow.com/questions/786 ... -flask-app