Колба застряла при загрузке после открытия определенного маршрута с функцией - PullRequest
0 голосов
/ 02 июля 2018

Я относительно новичок в Python и Flask. Я пытался создать веб-приложение, которое считывает показания данных из файла .txt и выводит их на график matplotlib. В этом веб-приложении у меня есть первая страница с 3 кнопками. Эти кнопки перенаправляют на разные маршруты с функциями, которые читают данные и наносят их на график matplotlib. Веб-приложение отлично работает только в первый раз, когда я иду по любому из этих маршрутов. После этого ничего не загружается. Я предполагаю, что у меня есть какой-то бесконечный цикл, но я не могу понять это. Кроме того, после того, как сайт застревает, процесс Python начинает потреблять больше ресурсов.

Проблема сохраняется только тогда, когда я открываю этот маршрут в веб-приложении:

@app.route("/temperature/")

Он загружается без проблем на веб-страницу, но только один раз, и все веб-приложение зависает, и я не могу получить доступ ни к одному из других маршрутов.

Заранее спасибо!

РЕДАКТИРОВАТЬ 1 - Весь код ниже

cloudapp.py (исходный код Python, который запускает Flask и функции)

from flask import Flask
from flask import render_template
from flask import request
import numpy as np
import matplotlib.pyplot as plt, mpld3
from datetime import datetime

app = Flask(__name__, template_folder='C:\Users\Valtteri\Desktop\cloudapp\Templates\HTML')
global all_lines

@app.route("/")
def frontpage():

    return render_template('frontpage.html')


@app.route("/temperature/")
def temperature():


    f = open('C:/Email/file.txt', 'r') 
    cpt = 0 # Line amount value
    all_lines = [] # List that has every Nth value 
    for line in f:
        cpt += 1 # Goes through every line and adds 1 to the counter
        # How often values are plotted (every Nth value)
        if cpt%100 == 0: 
            all_lines.append(line) # When 30th line is counted, add that line to all_lines[] list
        if cpt == 500: # How many values are plotted (counts from first)
            break

    dates = [str(line.split(';')[0]) for line in all_lines]
    date = [datetime.strptime(x,'%Y.%m.%d_%H:%M') for x in dates]
    y = [float(line.split(';')[1]) for line in all_lines]
    z = [float(line.split()[2]) for line in all_lines]

    fig, ax = plt.subplots()
    ax.plot_date(date, y, 'r-')

    f.close()
    return mpld3.fig_to_html(fig)
if __name__ == "__main__":
    app.run()

frontpage.html (шаблон HTML в папке .. \ templates \ html)

<!DOCTYPE html>
<html>
  <head>
<meta charset="UTF-8">
    <title>Envic Oy Cloud</title>
  </head>
  <body>
  <div class="headers">
  <h1>Web-Application</h1>
  <h2> Version 0.0.1 </h2>
  </div>
  <div class="buttons">
  <h3 class="buttonheader">Logger 1</h3>

  <a class="templink" href="http://127.0.0.1:5000/temperature/" target="_blank"> Check temperature </a>
  </body>
</html>

Я использую Bash для Windows, чтобы запустить код с

export FLASK_APP=myCloud.py

flask run

РЕДАКТИРОВАТЬ 2

Я пытался решить проблему долгое время, но не смог найти решение. Это как-то связано с совместимостью с Flask / mpld3. Я сделал то же самое веб-приложение, но на этот раз с помощью простой пирамиды WSGI. Теперь я могу обновлять график столько раз и перенаправлять себя в любой вид без зависания сервера. Я все еще оставлю пост нерешенным, потому что я все еще хотел бы использовать Flask. Я тоже продолжу свои исследования. Вот версия пирамиды, которая работает для меня:

from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
import numpy as np
import matplotlib.pyplot as plt, mpld3
from datetime import datetime

def hello_world(request):
    return Response('<h1>Testing the Pyramid version!</h1><a href="http://localhost:8888/second_view">Check temperature</a>')

def second_view(request):
    with open('C:/Email/file.txt') as f:   

        cpt = 0 # Line amount value
        all_lines = [] # List that has every Nth value 
        for line in f:
            cpt += 1 # Goes through every line and adds 1 to the counter
            # How often values are plotted (every Nth value)
            if cpt%100 == 0: 
                all_lines.append(line) # When 30th line is counted, add that line to all_lines[] list
            if cpt == 500: # How many values are plotted (counts from first)
                break

        dates = [str(line.split(';')[0]) for line in all_lines]
        date = [datetime.strptime(x,'%Y.%m.%d_%H:%M') for x in dates]
        y = [float(line.split(';')[1]) for line in all_lines]
        z = [float(line.split()[2]) for line in all_lines]

        plt.figure(figsize=(10,5))
        plt.title('Humidity', fontsize=15)
        plt.ylabel('Humidity RH', fontsize=15)


        fig = plt.figure()
        plot = plt.plot_date(date, z, 'b-')


        myfig = mpld3.fig_to_html(fig, template_type='simple')
    return Response(myfig)

if __name__ == '__main__':
    config = Configurator()
    config.add_route('hello_world', '/hello_world')
    config.add_route('second_view', '/second_view')
    config.add_view(hello_world, route_name='hello_world')
    config.add_view(second_view, route_name='second_view')
    app = config.make_wsgi_app()
    server = make_server('', 8888, app)
    server.serve_forever()

1 Ответ

0 голосов
/ 02 июля 2018

Вот то, что я пытался. У меня не было проблем с зависанием сервера после обновления или открытия новой вкладки ссылки. Однако после того, как я выключил сервер (Ctrl + C), консоль вызвала некоторые исключения, которые указывают на то, что mpld3 или matplotlib открыли некоторые новые потоки. В частности, исключение составляет RuntimeError: main thread is not in main loop.

Я немного погуглил и наткнулся на эту ссылку . Парень предложил использовать fig_to_dict с json. Я попробовал его решение, и все еще получал исключение.

Теперь я собираюсь записать оба подхода и позволить вам решить, какой использовать. Я не знаю, будет ли кто-нибудь из них работать на вас. Для моей настройки приложение работает нормально, несмотря на исключения после закрытия сервера.

Я также собираюсь использовать ваш пример, который не читал текстовый файл. У меня установлено отладочное значение True, поэтому я могу убедиться, что запросы GET обрабатываются при обновлении диаграммы или открытии нового экземпляра ссылки.

Подход 1 (fig_to_html)

app.py

from flask import Flask
from flask import render_template
import matplotlib.pyplot as plt
import mpld3


app = Flask(__name__, template_folder='/path/to/templates')


@app.route("/")
@app.route("/index")
def index():
    return render_template('frontpage.html')


@app.route('/temperature')
def temperature():
    date = ([1, 2, 3, 4])
    y = ([1, 2, 3, 4])

    fig = plt.figure(figsize=(10, 5))
    plt.title('Temperature', fontsize=15)
    plt.ylabel('Temperature' + u'\u2103', fontsize=15)

    plt.plot(date, y, 'b-')
    plt.ylim([0, 40])

    myfig = mpld3.fig_to_html(fig, template_type='simple')

    plt.clf()  # clear figure
    plt.cla()  # clear axes
    plt.close('all')  # close all figures

    # Print as HTML
    return myfig


if __name__ == "__main__":
    app.run(debug=True)  # run on debug mode

Подход 2 (fig_to_dict)

app.py

from flask import Flask
from flask import render_template
import matplotlib.pyplot as plt
import mpld3
import json


app = Flask(__name__, template_folder='/path/to/templates')


@app.route("/")
@app.route("/index")
def index():
    return render_template('frontpage.html')


@app.route('/temperature')
def temperature():
    date = ([1, 2, 3, 4])
    y = ([1, 2, 3, 4])

    fig = plt.figure(figsize=(10, 5))
    plt.title('Temperature', fontsize=15)
    plt.ylabel('Temperature' + u'\u2103', fontsize=15)

    plt.plot(date, y, 'b-')
    plt.ylim([0, 40])

    single_chart = dict()
    single_chart['id'] = "temp_figure"
    single_chart['json'] = json.dumps(mpld3.fig_to_dict(fig))

    plt.clf()  # clear figure
    plt.cla()  # clear axes
    plt.close('all')  # close figure

    # Print as HTML
    return render_template('temperature.html', single_chart=single_chart)


if __name__ == "__main__":
    app.run(debug=True)  # run on debug mode

А вот и файлы шаблонов. Я заметил, что вы использовали статическую ссылку в вашем frontpage.html, поэтому я заменил ее заполнителем, который позволяет Flask автоматически заполнять URL. У вас также был тег div, который вы не закрывали.

frontpage.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Envic Oy Cloud</title>
  </head>
  <body>
    <div class="headers">
      <h1>Web-Application</h1>
      <h2> Version 0.0.1 </h2>
    </div>
    <div class="buttons"></div>
    <h3 class="buttonheader">Logger 1</h3>
    <a class="templink" href="{{ url_for('temperature') }}" target="_blank"> Check temperature </a>
  </body>
</html>

Temperature.html (только для 2-го захода на посадку)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Sample Page</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
    <script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
    <script type="text/javascript" src="http://mpld3.github.io/js/mpld3.v0.2.js"></script>
  </head>
  <body>
    <div id="{{single_chart.id}}">
  </div>
  <script type="text/javascript">
    var figureId = "{{single_chart.id}}";
    var json01 = {{single_chart.json|safe}};
    mpld3.draw_figure(figureId, json01);
  </script>
  </body>
</html>

Кстати, я использую Python 3.5.4, Flask == 0.12.2, matplotlib == 2.1.2 и mpld3 == 0.3. Я тестировал с использованием Chrome версии 67.0.3396.87.

...