python socket_io.emit() 从函数调用
python socket_io.emit() call from function
我正在使用 aiohttp 和 python 构建网络服务器应用程序。对于数据交换,我使用 socketio python 实现。为了从我的前端获取数据到我的 python 脚本,一切都按预期工作。现在我想从我的 python 脚本发送一些数据以在浏览器中显示它。出于这个原因,我想实现一个发出给定数据的函数。
当我尝试直接调用 socket_io.emit('data',"test")
时,我收到运行时警告:
RuntimeWarning: coroutine 'AsyncServer.emit' was never awaited > my_server.socket_io.emit('data', "test")
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
我已经做了一些研究,我认为这是正常的。
当我像这样创建异步函数定义时:
async def sendData(dataOut):
await socket_io.emit('dataOut', dataOut)
没有发出消息
这是我的 python 测试代码:
from aiohttp import web
import socketio
socket_io = socketio.AsyncServer(async_mode='aiohttp')
app = web.Application()
socket_io.attach(app)
app.router.add_static('/', path=str('public/'))
configData = "testConfig"
dataOut ="testOut"
dataBack ="testBack"
async def index(request):
with open('public/index.html') as f:
return web.Response(text=f.read(), content_type='text/html')
app.router.add_get('/', index)
@socket_io.on('connect')
async def connect_handler(sid, environ):
print("new connection") # works as expected
await socket_io.emit('initial_config', configData) # works as expected
@socket_io.on("dataIn")
async def dataInHandler(sid, data):
print("new data") # works as expected
await socket_io.emit('dataBack', dataBack) # works as expected
async def sendData(dataOut):
await socket_io.emit('dataOut', dataOut)
web.run_app(app, host='XXX.XXX.XXX.XXX', port='XXXX')
sendData(dataOut) #is not doing anything
并且"public" HTML 使用的文件:
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>socketio Test</title>
</head>
<body>
<h1>socketio Test</h1>
<input type="checkbox" value="0" onClick="emit(id)" id="IN1"></input>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
<script>
const socket = io("http://XXX.XXX.XXX.XXX:XXXX");
function emit(id){
channel_obj = eval(id)
console.log(id, typeof(id), channel_obj.value, typeof(channel_obj.value))
if (channel_obj.value == 1){
channel_obj.value = 0
}
else{
channel_obj.value = 1
}
socket.emit("dataIn", id+":"+channel_obj.value);
}
socket.on("initial_config", function(data) {
console.log(data);
});
socket.on("dataBack", function(data) {
console.log(data);
});
socket.on("dataOut", function(data) {
console.log(data);
});
</script>
</body>
</html>
如何创建一个在调用时发出给定数据的函数?
编辑:
用于从另一个线程调用发射函数的新 python 脚本:
from aiohttp import web
import socketio, threading, time
configData = "testConfig"
dataOut ="testOut"
dataBack ="testBack"
data_flag = 0
connection_flag = 0
print("setup web-server")
socket_io = socketio.AsyncServer(async_mode='aiohttp')
app = web.Application()
socket_io.attach(app)
app.router.add_static('/', path=str('public/'))
async def index(request):
with open('public/index.html') as f:
return web.Response(text=f.read(), content_type='text/html')
app.router.add_get('/', index)
@socket_io.on('connect')
async def connect_handler(sid, environ):
global connection_flag
print("new connection") # works as expected
connection_flag = 1
await socket_io.emit('initial_config', configData) # works as expected
@socket_io.on("dataIn")
async def dataInHandler(sid, data):
print("new data") # works as expected
data_flag = 1
await socket_io.emit('dataBack', dataBack) # works as expected
async def sendData(dataOut):
await socket_io.emit('dataOut', dataOut)
def main():
global connection_flag
try:
print("in main loop")
time.sleep(1)
print("wait till a client connects")
while connection_flag == 0:
pass
print("wait 5 seconds")
time.sleep(5)
i = 0
while True:
print("now emitting: ", i)
sendData(i)
i += 1
time.sleep(1)
finally:
thread.join()
print("finished, exiting now")
thread = threading.Thread(target=main, args=())
thread.daemon=True
thread.start()
print("starting web-server")
web.run_app(app, host='192.168.132.210', port='5000')
重现步骤:
- 启动服务器,没有连接客户端:
setup web-server
in main loop
starting web-server
======== Running on http://192.168.132.210:5000 ========
(Press CTRL+C to quit)
wait till a client connects
- 通过浏览器连接
new connection
wait 5 seconds
now emitting: 0
aiohttp_thread.py:53: RuntimeWarning: coroutine 'sendData' was never awaited
sendData(i)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
now emitting: 1
now emitting: 2
now emitting: 3
now emitting: 4
now emitting: 5
问题出在脚本的最后两行:
web.run_app(app, host='XXX.XXX.XXX.XXX', port='XXXX')
sendData(dataOut) #is not doing anything
web.run_app()
调用是阻塞的,它启动网络服务器然后进入监听状态,永远不会返回(除非网络服务器被终止)。所以第二行永远没有机会执行。
所以您需要做的是找一个更好的时间调用 sendData()
,最好是在一个或多个客户端已经连接到服务器之后。一种选择是从客户端事件处理程序调用它,在您的情况下可以是 connect_handler()
或 dataInHandler()
函数。另一种选择是在启动 Web 服务器之前启动后台任务,该服务器以某种方式等待适当的时刻来发出数据。
对您的编辑的回复:
您混合使用 asyncio 和线程,这是行不通的。或者实际上,您不能跨线程使用 SocketIO 服务器,所有使用都必须在与异步循环相同的线程中。如果您需要后台任务,请使用协程。 Socket.IO 存储库有一个使用 socket_io.start_background_task()
函数启动的后台任务示例。
感谢 Miguel,我设法修复了我的代码,因此没有线程,而是使用 socketio 启动后台任务:
from aiohttp import web
import socketio, time, asyncio
configData = "testConfig"
dataOut ="testOut"
dataBack ="testBack"
data_flag = 0
connection_flag = 0
print("setup web-server")
socket_io = socketio.AsyncServer(async_mode='aiohttp')
app = web.Application()
socket_io.attach(app)
app.router.add_static('/', path=str('public/'))
async def index(request):
with open('public/index.html') as f:
return web.Response(text=f.read(), content_type='text/html')
app.router.add_get('/', index)
@socket_io.on('connect')
async def connect_handler(sid, environ):
global connection_flag
print("new connection") # works as expected
connection_flag = 1
await socket_io.emit('initial_config', configData) # works as expected
@socket_io.on("dataIn")
async def dataInHandler(sid, data):
print("new data") # works as expected
data_flag = 1
await socket_io.emit('dataBack', dataBack) # works as expected
async def sendData(dataOut):
await socket_io.emit('dataOut', dataOut)
async def main():
global connection_flag
try:
print("in main loop")
await asyncio.sleep(1)
print("wait till a client connects")
while connection_flag == 0:
pass
print("wait 5 seconds")
await asyncio.sleep(5)
i = 0
while True:
print("now emitting: ", i)
#await sendData(i)
await socket_io.emit('dataOut', i)
i += 1
await asyncio.sleep(1)
finally:
print("finished, exiting now")
socket_io.start_background_task(main)
print("starting web-server")
web.run_app(app, host='192.168.132.210', port='5000')
我正在使用 aiohttp 和 python 构建网络服务器应用程序。对于数据交换,我使用 socketio python 实现。为了从我的前端获取数据到我的 python 脚本,一切都按预期工作。现在我想从我的 python 脚本发送一些数据以在浏览器中显示它。出于这个原因,我想实现一个发出给定数据的函数。
当我尝试直接调用 socket_io.emit('data',"test")
时,我收到运行时警告:
RuntimeWarning: coroutine 'AsyncServer.emit' was never awaited > my_server.socket_io.emit('data', "test") RuntimeWarning: Enable tracemalloc to get the object allocation traceback
我已经做了一些研究,我认为这是正常的。
当我像这样创建异步函数定义时:
async def sendData(dataOut):
await socket_io.emit('dataOut', dataOut)
没有发出消息
这是我的 python 测试代码:
from aiohttp import web
import socketio
socket_io = socketio.AsyncServer(async_mode='aiohttp')
app = web.Application()
socket_io.attach(app)
app.router.add_static('/', path=str('public/'))
configData = "testConfig"
dataOut ="testOut"
dataBack ="testBack"
async def index(request):
with open('public/index.html') as f:
return web.Response(text=f.read(), content_type='text/html')
app.router.add_get('/', index)
@socket_io.on('connect')
async def connect_handler(sid, environ):
print("new connection") # works as expected
await socket_io.emit('initial_config', configData) # works as expected
@socket_io.on("dataIn")
async def dataInHandler(sid, data):
print("new data") # works as expected
await socket_io.emit('dataBack', dataBack) # works as expected
async def sendData(dataOut):
await socket_io.emit('dataOut', dataOut)
web.run_app(app, host='XXX.XXX.XXX.XXX', port='XXXX')
sendData(dataOut) #is not doing anything
并且"public" HTML 使用的文件:
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>socketio Test</title>
</head>
<body>
<h1>socketio Test</h1>
<input type="checkbox" value="0" onClick="emit(id)" id="IN1"></input>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
<script>
const socket = io("http://XXX.XXX.XXX.XXX:XXXX");
function emit(id){
channel_obj = eval(id)
console.log(id, typeof(id), channel_obj.value, typeof(channel_obj.value))
if (channel_obj.value == 1){
channel_obj.value = 0
}
else{
channel_obj.value = 1
}
socket.emit("dataIn", id+":"+channel_obj.value);
}
socket.on("initial_config", function(data) {
console.log(data);
});
socket.on("dataBack", function(data) {
console.log(data);
});
socket.on("dataOut", function(data) {
console.log(data);
});
</script>
</body>
</html>
如何创建一个在调用时发出给定数据的函数?
编辑:
用于从另一个线程调用发射函数的新 python 脚本:
from aiohttp import web
import socketio, threading, time
configData = "testConfig"
dataOut ="testOut"
dataBack ="testBack"
data_flag = 0
connection_flag = 0
print("setup web-server")
socket_io = socketio.AsyncServer(async_mode='aiohttp')
app = web.Application()
socket_io.attach(app)
app.router.add_static('/', path=str('public/'))
async def index(request):
with open('public/index.html') as f:
return web.Response(text=f.read(), content_type='text/html')
app.router.add_get('/', index)
@socket_io.on('connect')
async def connect_handler(sid, environ):
global connection_flag
print("new connection") # works as expected
connection_flag = 1
await socket_io.emit('initial_config', configData) # works as expected
@socket_io.on("dataIn")
async def dataInHandler(sid, data):
print("new data") # works as expected
data_flag = 1
await socket_io.emit('dataBack', dataBack) # works as expected
async def sendData(dataOut):
await socket_io.emit('dataOut', dataOut)
def main():
global connection_flag
try:
print("in main loop")
time.sleep(1)
print("wait till a client connects")
while connection_flag == 0:
pass
print("wait 5 seconds")
time.sleep(5)
i = 0
while True:
print("now emitting: ", i)
sendData(i)
i += 1
time.sleep(1)
finally:
thread.join()
print("finished, exiting now")
thread = threading.Thread(target=main, args=())
thread.daemon=True
thread.start()
print("starting web-server")
web.run_app(app, host='192.168.132.210', port='5000')
重现步骤:
- 启动服务器,没有连接客户端:
setup web-server
in main loop
starting web-server
======== Running on http://192.168.132.210:5000 ========
(Press CTRL+C to quit)
wait till a client connects
- 通过浏览器连接
new connection
wait 5 seconds
now emitting: 0
aiohttp_thread.py:53: RuntimeWarning: coroutine 'sendData' was never awaited
sendData(i)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
now emitting: 1
now emitting: 2
now emitting: 3
now emitting: 4
now emitting: 5
问题出在脚本的最后两行:
web.run_app(app, host='XXX.XXX.XXX.XXX', port='XXXX')
sendData(dataOut) #is not doing anything
web.run_app()
调用是阻塞的,它启动网络服务器然后进入监听状态,永远不会返回(除非网络服务器被终止)。所以第二行永远没有机会执行。
所以您需要做的是找一个更好的时间调用 sendData()
,最好是在一个或多个客户端已经连接到服务器之后。一种选择是从客户端事件处理程序调用它,在您的情况下可以是 connect_handler()
或 dataInHandler()
函数。另一种选择是在启动 Web 服务器之前启动后台任务,该服务器以某种方式等待适当的时刻来发出数据。
对您的编辑的回复:
您混合使用 asyncio 和线程,这是行不通的。或者实际上,您不能跨线程使用 SocketIO 服务器,所有使用都必须在与异步循环相同的线程中。如果您需要后台任务,请使用协程。 Socket.IO 存储库有一个使用 socket_io.start_background_task()
函数启动的后台任务示例。
感谢 Miguel,我设法修复了我的代码,因此没有线程,而是使用 socketio 启动后台任务:
from aiohttp import web
import socketio, time, asyncio
configData = "testConfig"
dataOut ="testOut"
dataBack ="testBack"
data_flag = 0
connection_flag = 0
print("setup web-server")
socket_io = socketio.AsyncServer(async_mode='aiohttp')
app = web.Application()
socket_io.attach(app)
app.router.add_static('/', path=str('public/'))
async def index(request):
with open('public/index.html') as f:
return web.Response(text=f.read(), content_type='text/html')
app.router.add_get('/', index)
@socket_io.on('connect')
async def connect_handler(sid, environ):
global connection_flag
print("new connection") # works as expected
connection_flag = 1
await socket_io.emit('initial_config', configData) # works as expected
@socket_io.on("dataIn")
async def dataInHandler(sid, data):
print("new data") # works as expected
data_flag = 1
await socket_io.emit('dataBack', dataBack) # works as expected
async def sendData(dataOut):
await socket_io.emit('dataOut', dataOut)
async def main():
global connection_flag
try:
print("in main loop")
await asyncio.sleep(1)
print("wait till a client connects")
while connection_flag == 0:
pass
print("wait 5 seconds")
await asyncio.sleep(5)
i = 0
while True:
print("now emitting: ", i)
#await sendData(i)
await socket_io.emit('dataOut', i)
i += 1
await asyncio.sleep(1)
finally:
print("finished, exiting now")
socket_io.start_background_task(main)
print("starting web-server")
web.run_app(app, host='192.168.132.210', port='5000')