4

I want to create a Python app where some data is retrieved and charted on a Dash app.

This is the Dash part. This is where my whole data will be sent and shown on a webpage, since I'm starting now, this is just a basic example of a live chart.

main.py

import dash
from dash.dependencies import Output, Event
import dash_core_components as dcc
import dash_html_components as html
import plotly
import random
import plotly.graph_objs as go
from collections import deque

app = dash.Dash(__name__)
app.layout = html.Div(
    [
        dcc.Graph(id='live-graph', animate=True),
        dcc.Interval(
            id='graph-update',
            interval=1*1000
        ),
    ]
)

@app.callback(Output('live-graph', 'figure'),
             events=[Event('graph-update', 'interval')])
def update_graph_scatter():
    X.append(X[-1]+1)
    Y.append(Y[-1]+Y[-1]*random.uniform(-0.1,0.1))

    data = plotly.graph_objs.Scatter(
            x=list(X),
            y=list(Y),
            name='Scatter',
            mode= 'lines+markers'
            )

    return {'data': [data],'layout' : go.Layout(xaxis=dict(range=[min(X),max(X)]), yaxis=dict(range=[min(Y),max(Y)]),)}

if __name__ == '__main__':
    app.run_server(debug=True)

This is the Python part where the data is retrieved, connecting to a Websocket.
data.py

import websocket
import json
from bitmex_websocket import Instrument
from bitmex_websocket.constants import InstrumentChannels
from bitmex_websocket.constants import Channels

websocket.enableTrace(True)

channels = [
    InstrumentChannels.trade,
]

XBTUSD = Instrument(symbol='XBTUSD',
                    channels=channels)
XBTUSD.on('action', lambda msg: test(msg))

XBTUSD = Instrument(symbol='XBTUSD',                       
                channels=channels)

XBTUSD.on('action', lambda msg: rekter(msg))

def rekter(msg):

    if msg['table'] =='trade':
        Rate = msg['data'][0]['price']

        print(Rate)


XBTUSD.run_forever()

I tried to accomplish that by using imports, so I imported as a module my script, but that didn't work either:

from trades import XBTUSD
import dash
from dash.dependencies import Output, Event
import dash_core_components as dcc
import dash_html_components as html
import plotly
import random
import plotly.graph_objs as go
from collections import deque


X = deque(maxlen=2000)
X.append(1)
Y = deque(maxlen=2000)
Y.append(1)


app = dash.Dash(__name__)
app.layout = html.Div(
    [
        dcc.Graph(id='live-graph', animate=True),
        dcc.Interval(
            id='graph-update',
            interval=1*1000
        ),
    ]
)

@app.callback(Output('live-graph', 'figure'),
              events=[Event('graph-update', 'interval')])
def update_graph_scatter():
    X.append(X[-1]+1)
    Y.append(Y[-1]+Y[-1]*random.uniform(-0.1,0.1))

    data = plotly.graph_objs.Scatter(
            x=list(X),
            y=list(Y),
            name='Scatter',
            mode= 'lines+markers'
            )

    return {'data': [data],'layout' : go.Layout(xaxis=dict(range=[min(X),max(X)]),
                                                yaxis=dict(range=[min(Y),max(Y)]),)}



if __name__ == '__main__':
    app.run_server(debug=True)

XBTUSD.run_forever()

Other than that, I tried turning it into modules, but it didn't work either.

My problem is that I don't know how to "embed" my second part into the first part. I tried do that, but if I put the lineXBTUSD.run_forever()before app.run_server(debug=True) only one part of the code will be executed and my whole Dash app won't run until I stop the first part of the code. Same happens if I do the opposite.

So the problem is XBTUSD.run_forever(), but I can't just remove that line because it won't run data.py. Is there a way to solve this?

I am now thinking of running two separated scripts with one sending data to a DB and the other one should query the DB, retrieve the data and chart it, but I don't know if it's the best solution because a) I'll be handling a lot of data every minute b) I don't know if it'll work when deployed online (on heroku, for example)

Ctrl S
  • 1,053
  • 12
  • 31
Jack022
  • 867
  • 6
  • 30
  • 91

1 Answers1

2

The answer is threading or multiprocessing, which will allow both methods to run at the same time. Changes to mutable objects take place in both threads/processes, so you would be able to communicate between your two functions as such. This post provides clarity on the issue.

  • 1
    Sounds like a valid solution, but would it allow me to "share" data/variable etc between the two scripts and would it work when deployed online, for example on Heroku? – Jack022 Nov 08 '18 at 20:54
  • As long as the data is mutable, i.e. not just a string or number, and as far as Heroku goes, a quick search looks like it's not impossible. – mhoffman2016 Nov 09 '18 at 02:17