I am using Flask to render graph from bokeh-server
from flask import Flask, render_template
from flask.ext.socketio import SocketIO, emit
import flask
from bokeh.plotting import figure, push
from bokeh.models import Range1d
from bokeh.embed import components
from bokeh.embed import autoload_server
from bokeh.session import Session
from bokeh.document import Document
from bokeh.models.renderers import GlyphRenderer
from flask.globals import current_app
app = Flask("Graph Realtime",static_url_path='/static')
app.config['SECRET_KEY'] = 'secret!'
app.debug = True
socketio = SocketIO(app)
#app.route('/')
def index():
x1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y1 = [0, 8, 2, 4, 6, 9, 5, 6, 25, 28, 4, 7]
# select the tools we want
TOOLS="pan,wheel_zoom,box_zoom,reset,save"
# the red and blue graphs will share this data range
xr1 = Range1d(start=0, end=30)
yr1 = Range1d(start=0, end=30)
# build our figures
p1 = figure(x_range=xr1, y_range=yr1, tools=TOOLS, plot_width=300, plot_height=300)
p1.scatter(x1, y1, size=12, color="red", alpha=0.5)
document = Document()
session = Session(root_url='http://localhost:5006/', load_from_config=False)
session.use_doc('graph')
session.load_document(document)
document.clear() # Semi-optional - see below
document.add(p1) # Put it on the server
session.store_document(document)
app_con = current_app._get_current_object().app_context()
app_con.g.p1 = p1.select(dict(type=GlyphRenderer))[0].data_source
script = autoload_server(p1, session)
return render_template('index.html', script=script)
I am saving the data source to g variable so that I can update it.
#socketio.on('my event', namespace='/test')
def test_message(message):
app = current_app._get_current_object()
with app.app_context():
print flask.g.p1
emit('my response', {'data': 'data'})
I am trying to update p1 if 'my event' happens.
But trying to access g variable raises error AttributeError: "'_AppCtxGlobals' object has no attribute 'p1'" error.
What am I doing wrong? Really appreciate the help.
Related
What I'm basically trying to do is use flask_uploads to find the path for an uploaded photo. I'm getting 'RuntimeError: no destination for set images' whenever I run the code. I've been over about 10 different tutorials and have gone over the code about 50 times. Please, for my sanity, help me out.
Here's my code
from colorthief import ColorThief
import matplotlib.pyplot as plt
from flask_uploads import configure_uploads, IMAGES, UploadSet
from flask import Flask, render_template, redirect, url_for, request
from flask_bootstrap import Bootstrap
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, FileField
import os
class InsertPic(FlaskForm):
image = FileField('Select Your Picture')
URL = 'D:\Python Porfolio\Colors\static\images'
app = Flask(__name__)
app.config['SECRET_KEY'] = '8BYkEfBA6O6donzWlSihBXox7C0sKR6b'
app.config['UPLOADED_PHOTOS_DEST'] = 'static/images'
Bootstrap(app)
images = UploadSet('images', IMAGES)
configure_uploads(app, images)
#app.route('/', methods=['GET', 'POST'])
def index():
form = InsertPic()
if form.validate_on_submit():
filename = images.save(form.image.data)
file_url = images.url(filename)
ct = ColorThief(f"{file_url}")
colors = ct.get_palette(color_count=11)
plt.imshow([[colors[a] for a in range(10)]])
plt.axis('off')
plt.savefig("output.jpg", bbox_inches='tight', pad_inches=0)
# Convet to HEX Values
separate_colors = []
for color in colors:
a = f"#{color[0]:02x}{color[1]:02x}{color[0]:02x}"
separate_colors.append(a)
return render_template('colors.html', colors=separate_colors)
return render_template('index.html', form=form)
if __name__ == "__main__":
app.run(debug=True)
Here's my Traceback info:
File "D:\prjects\pythonProject3\main.py", line 23, in <module>
configure_uploads(app, images)
File "D:\prjects\pythonProject3\venv\lib\site-packages\flask_uploads\flask_uploads.py", line 122, in configure_uploads
config = config_for_set(uset, app, defaults)
File "D:\prjects\pythonProject3\venv\lib\site-packages\flask_uploads\flask_uploads.py", line 84, in config_for_set
raise RuntimeError("no destination for set %s" % uset.name)
RuntimeError: no destination for set images
This is related to this post but the solution does not work.
I have SSO auth passing in a request header with a username. In a Flask app I can get the username back using flask.request.headers['username']. In Dash I get a server error. Here is the Dash app - it is using gunicorn.
import dash
from dash import html
import plotly.graph_objects as go
from dash import dcc
from dash.dependencies import Input, Output
import flask
from flask import request
server = flask.Flask(__name__) # define flask app.server
app = dash.Dash(__name__, serve_locally=False, server=server)
username = request.headers['username']
greeting = "Hello " + username
app.layout = html.Div(children=[
html.H1(children=greeting),
html.Div(children='''
Dash: A web application framework for Python.
'''),
dcc.Graph(
id='example-graph',
figure={
'data': [
{'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
{'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'},
],
'layout': {
'title': 'Dash Data Visualization'
}
}
)
])
if __name__ == '__main__':
app.run_server()
Any help would be much appreciated.
You can only access the request object from within a request context. In Dash terminology that means from within a callback. Here is a small example,
from dash import html, Input, Output, Dash
from flask import request
app = Dash(__name__)
app.layout = html.Div(children=[
html.Div(id="greeting"),
html.Div(id="dummy") # dummy element to trigger callback on page load
])
#app.callback(Output("greeting", "children"), Input("dummy", "children"))
def say_hello(_):
host = request.headers['host'] # host should always be there
return f"Hello from {host}!"
if __name__ == '__main__':
app.run_server()
I have a run.py file at the top level of my directory where I initialize flask-socketio. That file looks like this:
# /run.py
#!/usr/bin/env python
import os
from src.config import app_config
from dotenv import load_dotenv, find_dotenv
from flask_socketio import SocketIO
from src.app import create_app
load_dotenv(find_dotenv())
env_name = os.getenv('FLASK_ENV')
app = create_app(env_name)
socketio = SocketIO(app, async_mode=None)
if __name__ == '__main__':
port = os.getenv('PORT')
# run app
socketio.run(app, host='0.0.0.0', port=port)
My app.py file sits under src/app.py and looks like this:
def create_app(env_name):
"""
Create app
"""
# app initiliazation
app = Flask(__name__)
app.config.from_object(app_config[env_name])
# initializing bcrypt and db
bcrypt.init_app(app)
db.init_app(app)
app.register_blueprint(message_blueprint, url_prefix='/api/v1/message')
return app
I am trying to import the socketio instance into /src/views/MessageView.py
My MessageView.py file looks like this:
from ..models import db
from __main__ import socketio
from ..shared.Authentication import Auth
from threading import Lock
from flask import Flask, render_template, session, request, \
copy_current_request_context, g, Blueprint, json, Response
from flask_socketio import SocketIO, emit, join_room, leave_room, \
close_room, rooms, disconnect
message_api = Blueprint('message_api', __name__)
thread = None
thread_lock = Lock()
def background_thread():
"""Example of how to send server generated events to clients."""
count = 0
while True:
socketio.sleep(10)
count += 1
socketio.emit('my_response',
{'data': 'Server generated event', 'count': count},
namespace='/test')
#message_api.route('/')
def index():
return render_template('index.html', async_mode=socketio.async_mode)
#socketio.on('my_event', namespace='/test')
def test_message(message):
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': message['data'], 'count': session['receive_count']})
#socketio.on('my_broadcast_event', namespace='/test')
def test_broadcast_message(message):
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': message['data'], 'count': session['receive_count']},
broadcast=True)
#socketio.on('join', namespace='/test')
def join(message):
join_room(message['room'])
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': 'In rooms: ' + ', '.join(rooms()),
'count': session['receive_count']})
#socketio.on('leave', namespace='/test')
def leave(message):
leave_room(message['room'])
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': 'In rooms: ' + ', '.join(rooms()),
'count': session['receive_count']})
#socketio.on('close_room', namespace='/test')
def close(message):
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response', {'data': 'Room ' + message['room'] + ' is closing.',
'count': session['receive_count']},
room=message['room'])
close_room(message['room'])
#socketio.on('my_room_event', namespace='/test')
def send_room_message(message):
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': message['data'], 'count': session['receive_count']},
room=message['room'])
#socketio.on('disconnect_request', namespace='/test')
def disconnect_request():
#copy_current_request_context
def can_disconnect():
disconnect()
session['receive_count'] = session.get('receive_count', 0) + 1
# for this emit we use a callback function
# when the callback function is invoked we know that the message has been
# received and it is safe to disconnect
emit('my_response',
{'data': 'Disconnected!', 'count': session['receive_count']},
callback=can_disconnect)
#socketio.on('my_ping', namespace='/test')
def ping_pong():
emit('my_pong')
#socketio.on('connect', namespace='/test')
def test_connect():
global thread
with thread_lock:
if thread is None:
thread = socketio.start_background_task(background_thread)
emit('my_response', {'data': 'Connected', 'count': 0})
#socketio.on('disconnect', namespace='/test')
def test_disconnect():
print('Client disconnected', request.sid)
I have spent the last two days scouring the internet for help on how to fix this. The error i receive is:
ImportError: cannot import name 'socketio'
I have tried relative imports as well as monkey_patching. But each time the error still occurs. Any ideas on how to fix the issue would be greatly appreciated.
P.S. I am adapting the example that Miguel has in his flask-socketio repo located here: link. In his example, everything sits in one file, which would work in a basic app, however, for an app with 50+ API endpoints, that is not an optimal solution.
Why do you have the SocketIO object in the top-level run.py module? Since this is a Flask extension, it is better to have it with all your other extensions in src/app.py:
from flask_socketio import SocketIO
socketio = SocketIO()
def create_app(env_name):
"""
Create app
"""
# app initiliazation
app = Flask(__name__)
app.config.from_object(app_config[env_name])
# initializing bcrypt and db
bcrypt.init_app(app)
db.init_app(app)
# initialize socketio
socketio.init_app(app)
app.register_blueprint(message_blueprint, url_prefix='/api/v1/message')
return app
Then in run.py you can import this object:
from src.app import create_app, socketio
# ...
env_name = os.getenv('FLASK_ENV')
app = create_app(env_name)
# ...
if __name__ == '__main__':
port = os.getenv('PORT')
# run app
socketio.run(app, host='0.0.0.0', port=port)
And in the same way you can import it in your MessageView.py module:
from src.app import socketio
socketio.on('whatever')
def do_something(data):
pass
I have a complete example application that uses this structure here: https://github.com/miguelgrinberg/Flask-SocketIO-Chat.
I am new to bokeh. I am struggling to get around error 404 when using AjaxDataSource . Following is the simple code which will update the plot every 2 seconds.
from flask import Flask, render_template, request, jsonify
from bokeh.embed import components
from bokeh.plotting import figure
from bokeh.models.sources import AjaxDataSource
app = Flask(__name__)
x = 0
#app.route('/data/', methods=['POST'])
def data():
global x
x += 1
y = 2 ** x
return jsonify(x=x, y=y)
#app.route("/dash")
def showChanges():
plots = []
plots.append(funcEmbedFig())
return render_template('extendTest.html', plots=plots)
def funcEmbedFig():
source = AjaxDataSource(data_url=request.url_root + 'data/',
polling_interval=2000, mode='append')
source.data = dict(x=[], y=[])
plot = figure(plot_height=300, sizing_mode='scale_width')
plot.line('x', 'y', source=source, line_width=4)
script, div = components(plot)
return script, div
if __name__ == '__main__':
app.run()
How can I get around this?
Any help would be much useful,
Thanks.
Have you tried flask’s url_for(“data”) as the data_url parameter?
I am using zipline to backtest with the local data, but it seems unsuccessful.
from datetime import datetime
import pytz
import pandas as pd
from zipline.algorithm import TradingAlgorithm
import zipline.utils.factory as factory
class BuyApple(TradingAlgorithm):
def handle_data(self, data):
self.order('AAPL', 1)
if __name__ == '__main__':
data = pd.read_csv('AAPL.csv')
simple_algo = BuyApple()
results = simple_algo.run(data)
above is my code, When I run this script, I got the message:
[2015-04-03 01:41:53.712035] WARNING: Loader: No benchmark data found for date range.
start_date=2015-04-03 00:00:00+00:00, end_date=2015-04-03 01:41:53.632300, url=http://ichart.finance.yahoo.com/table.csv?a=3&c=2015&b=3&e=3&d=3&g=d&f=2015&s=%5EGSPC
Traceback (most recent call last):
File "bollinger.py", line 31, in <module>
results = simple_algo.run(data)
File "/home/xinzhou/.local/lib/python2.7/site-packages/zipline-0.7.0-py2.7.egg/zipline/algorithm.py", line 372, in run
source = DataFrameSource(source)
File "/home/xinzhou/.local/lib/python2.7/site-packages/zipline-0.7.0-py2.7.egg/zipline/sources/data_frame_source.py", line 42, in __init__
assert isinstance(data.index, pd.tseries.index.DatetimeIndex)
AssertionError
Then I change my code to below:
from datetime import datetime
import pytz
import pandas as pd
from zipline.algorithm import TradingAlgorithm
import zipline.utils.factory as factory
class BuyApple(TradingAlgorithm):
def handle_data(self, data):
self.order('AAPL', 1)
if __name__ == '__main__':
start = datetime(2000, 1, 9, 14, 30, 0, 0, pytz.utc)
end = datetime(2001, 1, 10, 21, 0, 0, 0, pytz.utc)
data = pd.read_csv('AAPL.csv', parse_dates=True, index_col=0)
sim_params = factory.create_simulation_parameters(
start=start, end=end, capital_base=10000)
sim_params.data_frequency = '1d'
sim_params.emission_rate = '1d'
simple_algo = BuyApple()
results = simple_algo.run(data)
The
assert isinstance(data.index, pd.tseries.index.DatetimeIndex)
AssertionError
is gone. But in my terminal, it keeps in this message:
[2015-04-03 01:44:28.141657] WARNING: Loader: No benchmark data found for date range.
start_date=2015-04-03 00:00:00+00:00, end_date=2015-04-03 01:44:28.028243, url=http://ichart.finance.yahoo.com/table.csv?a=3&c=2015&b=3&e=3&d=3&g=d&f=2015&s=%5EGSPC
How to solve this problem? Thanks.
data.index=pd.to_datetime(data.index)
data.index=data.index.tz_localize(pytz.utc)
The next code works for me.Is a version of the tutorial example "My first Algorithm" (http://www.zipline.io/tutorial/) .Data must be in ascending order by date. Run as a normal python program( python yourfilename.py):
import pytz
from datetime import datetime
from zipline.algorithm import TradingAlgorithm
from zipline.api import order, record, symbol
import pandas as pd
# Load data manually csv
#Date,Open,High,Low,Close,Volume,Adj Close
#1984-09-07,26.5,26.87,26.25,26.5,2981600,3.02
#...
parse = lambda x: pytz.utc.localize(datetime.strptime(x, '%Y-%m-%d'))
data=pd.read_csv('aapl.csv', parse_dates=['Date'], index_col=0,date_parser=parse)
# Define algorithm
def initialize(context):
pass
def handle_data(context, data):
order('Close',10)
record(AAPL=data['Close'])
# Create algorithm object passing in initialize and
# handle_data functions
algo_obj = TradingAlgorithm(initialize=initialize,
handle_data=handle_data)
# Run algorithm
perf_manual = algo_obj.run(data)
# Print
perf_manual.to_csv('output.csv'