Flask-SocketIO 多线程遇到的问题

2021-04-14 10:48:53 +08:00
 Alexf4

最近在使用 Flask-SocketIO 想实现实时跟踪 celery 的任务日志(每个任务一个日志文件)的功能。 在本地运行,开了两个窗口,第二个窗口会输出自己的日志,第一个窗口会输入自己的加后一个窗口的日志。类似后续每开的一个窗口,前面的窗口都会 append 此窗口的日志。

client

import sys

import socketio


client = socketio.Client(reconnection=False)


@client.on('log', namespace='/cdc')
def on_log(args):
    print(args['data'])


def send(log_path):
    try:
        client.connect('http://127.0.0.1:5000', namespaces='/cdc')
        client.emit('log', {'log_path': log_path}, namespace='/cdc')
    except KeyboardInterrupt:
        try:
            sys.exit(0)
        except SystemExit:
            sys.exit(1)

server

sio = flask_socketio.SocketIO(async_mode=async_mode)


@sio.on('log', namespace='/cdc')
def log(data):
    thread = sio.start_background_task(scan_log, data['log_path'], None, flask.request.sid)


def scan_log(log_path, app=None, client_id=None):
    counter = 0

    with open(log_path, 'r') as f:
        while True:
            line = f.readline()
            if not line:
                sio.sleep(0.1)
                continue
            counter += 1
            sio.emit('log', {'data': line.strip()}, namespace='/cdc', to=client_id)

各位有没有遇到类似的情况?或者有什么大概的思路?

2042 次点击
所在节点    Python
5 条回复
dassh
2021-04-14 11:18:09 +08:00
每个日志应该有一个独立的标识,然后 on_log 里对标识进行判断,如果是对应的才 print
Alexf4
2021-04-14 11:35:10 +08:00
@dassh 这里每一个日志都是独立的(每个任务都生成对应的日志)
所以 client on log 会接受 server 多个线程分别 emit 的数据?
我这个 scan log 不是用多个线程进行的么,另外 emit 的时候用 to 这个参数也区别了 client 的发送的呀
dassh
2021-04-14 11:47:37 +08:00
sio.on('log', ...)就表示你订阅了所有 server emit 的'log'的事件,所以你需要进行过滤判断,to 参数我没用过哈,给你一种解决方案
```

@client.on('log', namespace='/cdc')
def on_log(args):
if args['log_path'] == sys.argv[1] #这里的 sys.argv[1]就是你传入 log_path 的地址
print(args['data'])

def scan_log(log_path, app=None, client_id=None):
...
sio.emit('log', {'data': line.strip(), 'log_path': log_path}, namespace='/cdc', to=client_id)

```
Latin
2021-04-14 12:55:08 +08:00
同一楼加 uuid 过滤
Alexf4
2021-04-14 12:56:52 +08:00
@dassh 感谢你的思路~
- to 的参数我测试了下, 在不调用 `start_background_task ` 的情况下,可以完成独立 print 功能
- 在调用 `start_background_task ` 才会出现提到的,旧的窗口也会获取到新窗口的数据(日志数据)
- 所以是比较想好奇这一块的实现方式或者原理

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/770515

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX