python - 从greenlet中的标准输出非阻塞读取
问题描述
我有一个带有 SocketIO 的烧瓶应用程序。因此,我选择使用该eventlet
库运行应用程序。如果我没记错的话,在后台,eventlet 使用绿色线程来实现并发。
在我的应用程序中,我想生成一个进程并通过 Web 套接字流式传输输出。下面是一个玩具示例
# 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
解决方案
推荐阅读
- javascript - 我需要将变量传递给从 php exec 命令调用的 javascript
- ruby-on-rails - Rails 5 has_many_through 在结果中包含数据透视表
- javascript - 使用 jQuery $(this).addClass() 会破坏工作代码
- ruby-on-rails - ActiveJob retry_on 回调被忽略
- javascript - libphonenumber-js 是否与 Angular 的 buildOptimizer 选项兼容?
- r - 反转堆叠条形图的顺序 - 在 ggplot 中突出显示
- python - 切出三角形并将它们混合
- javascript - React-Native 按对象内的日期值对对象数组进行排序
- python-3.x - 有什么方法可以绕过将新变量映射到从 python 函数返回的元组值的需要?
- reactjs - 从 Redux 状态数组中移除多个对象