Исключение в ошибке потока при обновлении моего dict, содержащего список сообщений в flask -socketio - PullRequest
1 голос
/ 17 июня 2020

Я создаю приложение для чата basi c для проекта cs502.

У меня есть dict, в котором хранятся все мои сообщения с именем пользователя, временем и сообщением, а значения содержимого сообщения находятся в список.

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

Exception in thread Thread-5:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/socketio/server.py", line 682, in _handle_event_internal
    r = server._trigger_event(data[0], namespace, sid, *data[1:])
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/socketio/server.py", line 711, in _trigger_event
    return self.handlers[namespace][event](*args)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/flask_socketio/__init__.py", line 282, in _handler
    return self._handle_event(handler, message, namespace, sid,
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/flask_socketio/__init__.py", line 713, in _handle_event
    ret = handler(*args)
  File "/Users/aparep7474/Desktop/project2/application.py", line 103, in post
    if len(messages_created[session['current_channel']]) > 100:
KeyError: 'Hello'

Когда пользователь нажимает кнопку публикации, он принимает значение поля ввода, а затем генерирует функцию отправки сообщения. Затем его получает мое приложение flask, где оно добавляет информацию к dict и выдает сообщение, которое будет динамически показано пользователю.

Мой Flask код:

Большая часть важный код находится в конце

import os, requests

from flask import Flask, session, redirect, render_template, request, jsonify
from flask_socketio import SocketIO, emit

from helpers import login_required

app = Flask(__name__)
app.config["SECRET_KEY"] = "4301"
socketio = SocketIO(app, async_mode='eventlet')

users_online = []

channels_created = []

messages_created = {}


@app.route("/")
@login_required
def index():

    if session.get("current_channel") is None:
        return redirect("/create_channel")

    else:
        return redirect("/channels/" + session.get("current_channel"))


@app.route("/log_in", methods=['GET','POST'])
def log_in():

    username = request.form.get("username")

    if request.method == "POST":

        if len(username) == 0:
            return render_template("error.html", message="username can't be empty.")

        if username in users_online:
            return render_template("error.html", message="that username already exists.")

        users_online.append(username)

        session['username'] = username

        session.permanent = True

        return redirect("/create_channel")

    else:
        return render_template("log_in.html")


@app.route("/log_out", methods=['GET','POST'])
def log_out():

    try:
        users_online.remove(session['username'])
    except ValueError:
        pass

    session.clear()

    return redirect("/")


@app.route("/create_channel", methods=['GET','POST'])
@login_required
def create_channel():

    session.pop("current_channel", None)

    new_channel = request.form.get("channel")

    if request.method == "POST":

        if new_channel in channels_created:
            return render_template("error.html", message="that channel already exists.")

        channels_created.append(new_channel)

        return redirect("/channels/" + new_channel)

    else:
        return render_template("create_channel.html", channels=channels_created)


@app.route("/channels/<channel>", methods=['GET','POST'])
@login_required
def channel_name(channel):

    session['current_channel'] = channel

    session.permanent = True

    return render_template("channel.html", channels=channels_created)


@socketio.on("submit post")
def post(data):

    if len(messages_created[session['current_channel']]) > 100:
        messages_created[session['current_channel']].pop(0)

    messages_created[session['current_channel']].append([session.get("username"), data["message"], datetime.now().strftime("%H:%M")])

    message = data["message"]

    time = datetime.now().strftime("%H:%M")

    emit("announce post", {"message": message, "time": time, "username": session.get("username")}, room=room, broadcast=True)


if __name__ == '__main__':
    socketio.run(app, debug=True)

Мой HTML Код:

{% extends "layout.html" %}

{% block title %}
  {{ session.current_channel }}
{% endblock %}

{% block head %}
  <style>
    #box {
      box-sizing: border-box;
      border-radius: 5px;
      width: 100%;
      padding: 10px;
      border: 1px solid gray;
      margin: 0;
    }
  </style>
  <script src="{{url_for('static', filename='channel.js')}}"></script>
{% endblock %}

{% block content %}
  <h1 class="text-center">{{ session.current_channel }}</h1>
  <body>
    <div id="box">
      {% if messages_created %}
        {% for message in messages_created %}
          <ul>
            <li><strong> {{ message[0] }} </strong> : {{ message[1] }} <small class="float-right"> {{ message[2] }} </small></li>
          </ul>
          {% endfor %}
        {% endif %}
        <ul id="posts">
        </ul>
      </div>
    <hr>
    <form id="form">
      <input id="message" autofocus autocomplete="off" placeholder="Enter Your Post Here" style="height: 40px;width: 800px;" class="mt-3">
      <button id="button" class="btn btn-secondary">Post</button>
    </form>
  </body>
{% endblock %}

Макет. html просто содержит панель навигации, которая просто содержит раскрывающийся список с каналами и кнопка выхода.

Наконец мой JS Код:

document.addEventListener('DOMContentLoaded', () => {

  var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);

  socket.on('connect', () => {
    document.querySelector('#form').onsubmit = () => {
      const message = document.querySelector('#message').value;
      socket.emit('submit post', {'message': message});
      document.querySelector("#message").value = '';
      return false;
    };
  });

  socket.on('announce post', data => {
    console.log('received');
    const li = document.createElement('li');
    li.innerHTML = `<strong> ${data.username} </strong> : ${data.message} <small class="float-right"> ${data.time} </small>`;
    document.querySelector('#posts').append(li);
  });
});
...