socketio.emit() не работает при взаимодействии с использованием Popen в Windows в потоке

Я думаю, что краткий фрагмент кода лучше объяснит мою проблему, поэтому, пожалуйста, взгляните на это:

from flask import Flask
from flask.ext.socketio import SocketIO
from threading import Thread
import subprocess
import threading
from eventlet.green.subprocess import Popen

app = Flask(__name__)
socketio = SocketIO(app)

def get_tasks_and_emit():
    instance = Popen(["tasklist"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1)

    lines_iterator = iter(instance.stdout.readline, b"")
    data = ""
    for line in lines_iterator:
        data += line.decode("utf8")

    socketio.emit("loaded", data)

    print("::: DEBUG - returned tasks with thread")

@app.route("/")
def index():
    html = "<!DOCTYPE html>"
    html += "<script src=https://code.jquery.com/jquery-2.2.0.min.js></script>"
    html += "<script src=https://cdn.socket.io/socket.io-1.4.5.js></script>"
    html += "<script>"
    html += "var socket = io.connect(window.location.origin);"
    html += "socket.on('loaded', function(data) {alert(data);});"
    html += "function load_tasks_threaded() {$.get('/tasks_threaded');}"
    html += "function load_tasks_nonthreaded() {$.get('/tasks');}"
    html += "</script>"
    html += "<button onclick='load_tasks_nonthreaded()'>Load Tasks</button>"
    html += "<button onclick='load_tasks_threaded()'>Load Tasks (Threaded)</button>"
    return html


@app.route("/tasks")
def tasks():
    get_tasks_and_emit()
    print("::: DEBUG - returned tasks without thread")
    return ""

@app.route("/tasks_threaded")
def tasks_threaded():
    threading.Thread(target=get_tasks_and_emit).start()
    return ""

if __name__ == "__main__":
    socketio.run(app, port=7000, debug=True)

Я запускаю этот код в Windows с помощью eventlet, если я не использую eventlet, все в порядке (но, конечно, намного медленнее из-за режима потоковой обработки werkzeug). (И я только что проверил, и в Linux он тоже не работает)

Я надеюсь, что кто-то может указать мне в правильном направлении. (Кстати, моя версия Python 3.5.1)


person John Reese    schedule 06.02.2016    source источник
comment
Вы также можете использовать from eventlet.green import threading вместо исправления обезьяны. Пожалуйста, поместите решение в сообщение с ответом ниже, чтобы другие люди с похожей проблемой могли легко понять, что делать.   -  person temoto    schedule 07.02.2016


Ответы (1)


Я нашел проблему. По-видимому, вам нужно исправить модуль потоковой обработки, поэтому я добавил

import eventlet
eventlet.monkey_patch(thread=True)

а то у меня тоже была проблема с долго работающими программами. У меня была та же проблема, что и у парня в этом сообщении StackOverflow: request">Использование Popen в потоке блокирует каждый входящий запрос Flask-SocketIO

Поэтому я добавил

eventlet.sleep()

к циклу for, который обрабатывает каналы.

РЕДАКТИРОВАТЬ: Как указал temoto, в качестве альтернативы можно просто использовать модуль потоковой передачи из eventlet.green следующим образом:

from eventlet.green import threading 
person John Reese    schedule 09.02.2016