0

I am having an odd behavior in my FLASK project and I am not really sure what is going on here, basically it works OK while the developer tools of the browser is open (tested in firefox/chrome) but it stops updating as soon as I close it.

I have a Thread in FLASK that is emitting current date and pH values (read from a pH probe) and also appending the data to a csv file that i later read in the js to make a graph and refresh it every time I have a new pH reading. In python:

....
#Inside the thread. Running every 5 seconds.
socketio.emit('new_pH', {'pH': pH[0],'date': date})
with open("static/data.csv", "a") as myfile:
      myfile.write("{},{}\n".format(date,pH[0]))
print("pH: {}".format(pH[0]))
....

and on the js side:

var socket = io.connect('http://' + document.domain + ':' + location.port,{'multiplex': false});
socket.on('new_pH', function(msg){
....
    console.log("Received pH: ", msg.pH)
    console.log("Received date: ", msg.date)
    d3.csv("static/data.csv", function(error, data) {
        data.forEach(function(d) {
            d.date = parseDate(d.date);
            d.close = +d.close;
....
  });

On my terminal I see that when the dev tools are open I have a GET request for the data:

pH: 7.64666214035
127.0.0.1 - - [22/Nov/2017 18:11:39] "GET /static/data.csv HTTP/1.1" 200 4950 0.000831

and as soon as I close the devel tools I only see the pH values.

It happens with the FLASK server and also with gunicorn gunicorn --worker-class eventlet -w 1 pHMon:app -b 0.0.0.0:5000 --reload

Any hint would be appreciated! Thanks!

Python code:

from flask import Flask, render_template, g, redirect
from flask_socketio import SocketIO, emit

import numpy as np
import threading
import eventlet
import datetime
import sqlite3
import time

from models import db

eventlet.monkey_patch()

class rand_pH(object):
    def __init__(self, interval, exp_id):
        self.interval = interval
        self.exp_id = exp_id
        thread = threading.Thread(target=self.run, args=())
        thread.daemon = True                            
        thread.start()       
        # Initialice the textfile
        with open("static/data.csv", "w") as myfile:
            myfile.write("date,close\n")

    def run(self):
        """
        Runs forever in the backround
        Used to emit the state of the system
        Now it just send a new pH every 5 seconds
        But will be replaced by the actual reading
        """
        global pH
        global current_status_loop
        current_status_loop = get_current_status()

        while current_status_loop==1:
            s = np.random.normal(0, 0.5, 1)
            pH=pH+s
            date=datetime.datetime.today().strftime("%Y-%m-%d %H:%M:%S")
            socketio.emit('new_pH', {'pH': pH[0],'date': date})
            # Update the database
            conn = sqlite3.connect('database.db')
            cursor = conn.cursor()
            cursor.execute('''INSERT INTO experiment_data(date, value, exp_id) VALUES(?,?,?)''', (date,pH[0],self.exp_id))
            conn.commit()
            with open("static/data.csv", "a") as myfile:
                myfile.write("{},{}\n".format(date,pH[0]))
            time.sleep(self.interval)
            current_status_loop = get_current_status()


@app.route('/')
def index():
    '''Main access point'''
    # Get the status of the last experiment
    cursor = get_db().cursor()
    cursor.execute(''' SELECT status FROM exp ORDER BY exp_id DESC LIMIT 1 ''')
    current_status = cursor.fetchall()[0][0]
    # if current_status_loop is not defined it means that
    # the thread was not started (ie. previous enexpected server shutownd
    # or not an expement runnin).
    try:
        current_status_loop
    except NameError:
        stop()
    return render_template('start_new.html')
    else:
        print "sure, it was defined."
    if current_status == 0:
       return render_template('start_new.html')
    if current_status == 1:
       return render_template('view_running.html')

JS

var socket = io.connect('http://' + document.domain + ':' + location.port,{'multiplex': false});

socket.on('new_pH', function(msg){
  console.log("Recived pH: ", msg.pH)
  console.log("Recived date: ", msg.date)
  // Get the data
  d3.csv("static/data.csv", function(error, data) {
    data.forEach(function(d) {
    d.date = parseDate(d.date);
    d.close = +d.close;
    });
  // Set the ranges
  var x = d3.time.scale().range([0, width]);
  var y = d3.scale.linear().range([height, 0]);

  // Define the axes
  var xAxis = d3.svg.axis().scale(x)
  .orient("bottom").ticks(2);

  var yAxis = d3.svg.axis().scale(y)
  .orient("left").ticks(2);

  // Define the line
  var valueline = d3.svg.line()
  .x(function(d) { return x(d.date); })
  .y(function(d) { return y(d.close); });

  // Scale the range of the data
  x.domain(d3.extent(data, function(d) { return d.date; }));
  y.domain([0, d3.max(data, function(d) { return d.close; })]);

  // Add the valueline path.
  svg.append("path")
  .attr("class", "line")
  .attr("d", valueline(data));

  // Add the X Axis
  svg.append("g")
  .attr("class", "x axis")
  .attr("transform", "translate(0," + height + ")")
  .call(xAxis);

  // Add the Y Axis
  svg.append("g")
  .attr("class", "y axis")
  .call(yAxis);

});
});
  • I can't really tell you, since you are not showing the complete application. But I'm pretty sure the dev tools open or closed is a side effect, not part of the problem. So let's go through the check list: First, have you monkey patched the standard library, and second: are you sure you are not invoking any blocking functions in your Python server? – Miguel Grinberg Nov 23 '17 at 01:46
  • Thanks for the answer. I'll update the question to include the relevant code. Yes I have `eventlet.monkey_patch()`. As I mentioned the datafile gets updated properly. This happens just 1 line bellow I emit the socket.io signal, so I do not think there is anything wrong there. – Leonardo Hardtke Nov 23 '17 at 02:53
  • Try monkey patching above your imports, not below. – Miguel Grinberg Nov 23 '17 at 03:25
  • Thanks, but it does not work either. :( – Leonardo Hardtke Nov 23 '17 at 04:31
  • Well I figured out what the problem was. I was trying to read the static data file, instead of serving the data to a route. Working OK now. Sorry for the noise... – Leonardo Hardtke Nov 23 '17 at 06:13

0 Answers0