У меня есть приложение flask с SocketIO. В связи с этим я решил запустить приложение, используя библиотеку eventlet
. Под капотом eventlet используется зеленые потоки для достижения параллелизма, если я не ошибаюсь.
В моем приложении я хочу порождать процесс и передавать вывод через веб-сокеты. Ниже приведен игрушечный пример
# eventlet==0.25.1
# flask==1.1.1
# flask-socketio==4.2.1
import eventlet
import subprocess
from flask import Flask, jsonify
from flask_socketio import SocketIO
app = Flask(__name__)
socketio = SocketIO(app)
socketio.init_app(app, cors_allowed_origins='*')
@app.route('/ping')
def start_ping():
eventlet.spawn_n(ping)
return jsonify(success=True)
@app.route('/hello')
def hello():
return jsonify(data='Hello World')
def ping():
proc = subprocess.Popen(
('ping', '-t', 'google.com'),
stdout=subprocess.PIPE,
)
for line in proc.stdout:
eventlet.sleep(0.5)
socketio.emit('log_receive', str(line))
if __name__ == '__main__':
socketio.run(app)
- Пользователь достигает конечной точки
/ping
. - Функция
ping()
выполняется в зеленом потоке, который запускает команду ping у дочернего элемента строки процесса - считываются из стандартного вывода подпроцесса, а
emited
через веб-сокеты eventlet.sleep(0.5)
используется для обеспечения возможности запуска других частей приложения.
Вопрос:
for line in proc.stdout:
блокируется. До тех пор, пока что-то не пройдет через стандартный вывод, eventlet.sleep(0.5)
не будет выполняться, и, следовательно, остальной части приложения не будет предоставлена возможность запуска. Таким образом, рендеринг приложения, не отвечает.
Я натолкнулся на этот вопрос о том, как выполнять неблокирующее чтение из subprocess.PIPE
, и предлагается по существу использовать отдельный поток для чтения.
К сожалению, я не могу использовать отдельный поток из-за модели параллельного / сопрограммного программирования, которой я ограничен из-за eventlet / greenlet.
Я мог бы использовать fcntl () для выполнения неблокирующих операций чтения, но я на windows, и поэтому это не вариант
Что является альтернативой избегайте того, чтобы приложение находилось во власти подпроцесса stdout