Python Socketio를 사용할 때 별도의 함수 처리기 모듈

이 기사에서는 Socketio 이벤트 핸들러에 대해 별도의 모듈을 가질 수 있는 방법을 보여줍니다. 모두 같은 파일에 보관하는 대신.

바라건대 이것은 상대적으로 짧은 기사가 되어야 합니다.

기본



이 예제에서는 FastAPI와 함께 SocketIO를 사용하지만 이 코드를 SocketIO 전용으로 쉽게 변경할 수 있습니다. 나는 또한 uvicorn을 사용하여 서버를 실행할 것입니다.

예를 들어

import uvicorn
from pydantic import BaseModel


async def startup():
    print("Starting Application")


sio = socketio.AsyncServer(async_mode="asgi")
app = socketio.ASGIApp(sio, on_startup=startup)


class FooEvent(BaseModel):
    name: str


@sio.on("FOO")
async def foo_event(sid, *args, **kwargs):
    data = FooEvent(**args[0])
    await sio.emit("BAR", {"foo": data.name})


if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8080)



여기에서 FastAPI 애플리케이션을 설정하고 하위 애플리케이션으로 Socketio 서버를 생성하고 마운트합니다.

:::참고 fastapi-socketio

여기서는 fastapi-socketio 라이브러리를 사용하여 애플리케이션을 Fastapi 앱에 마운트하는 작업을 처리합니다. 그러나 이 작업은 라이브러리 없이도 수행할 수 있습니다. 예를 보려면 여기Github issue를 참조하십시오.:::

어쨌든 우리는 FastAPI 없이 Socketio 전용 서버를 생성하는 것과 같이 간단하게 할 수 있습니다.

import socketio

sio = socketio.AsyncServer()
application = socketio.ASGIApp(sio)


핸들러 모듈



다음으로 클라이언트에서 수신해야 하는 다양한 이벤트를 처리할 모듈을 살펴보겠습니다.

from app.main import socket_manager as sm


@sm.on("FOO")
async def foo_event(sid, *args, **kwargs):
    await sm.emit("BAR", {"response": "hello world!"})



보시다시피 이 핸들러는 두 번째 예에서 소켓 관리자 객체를 가져옵니다. 이것은 sio 라는 객체입니다. 그런 다음 함수를 장식합니다. 이 함수는 클라이언트가 웹 서버에 FOO 이벤트를 보낼 때마다 호출됩니다. 이 예제에서는 BAR 와 함께 hello world 이벤트를 반환합니다(방출합니다). 이 기능이 구체적으로 수행하는 작업은 실제로 중요하지 않습니다.

초기화.py



마지막으로 이 모든 것을 app/__init__.py 모듈에 넣겠습니다.

import uvicorn

import app.foo.foo_handlers
from app.main import application

app = application

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8080)



이것은 약간 혼란스러워 보일 수 있습니다. 본질적으로 이것은 uvicorn이 서버를 시작하기 위해 직접 호출하는 모듈입니다. 그런 다음 함수 핸들러import app.foo.foo_handlers를 가져올 때 여기에서 사용하지 않더라도 모든 함수 핸들러를 가져와야 합니다. 그래서 이것은 당신의 애플리케이션이 그것들이 존재한다는 것을 알기 위한 것입니다.

이 가져오기가 없으면 응용 프로그램이 앱에 "연결"할 방법이 없습니다. 이제 FOO 이벤트가 클라이언트에서 발생할 때마다 서버는 해당 기능을 보내는 것을 알고 있습니다.

마지막으로 응용 프로그램이 app = application 모듈에서 생성한 FastAPI/ASGIApp인 간단한 더미 변수main.py를 생성합니다. 이것을 응용 프로그램으로 남길 수 있지만 일반적으로 uvicorn 을 사용할 때, 즉 app 를 사용할 예제를 볼 때입니다. 그래서 여기서 이름을 바꿨습니다.

최종 블록은 실제로 필요하지 않습니다.

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8080)


이 모듈이 메인 파일로 사용되고 우리를 위해 uvicorn 서버를 시작하면 더 많이 존재합니다. 그러나 일반적으로 나는 보통 내 Docker 이미지 또는 launch.json(VSCode 디버거) 구성 등에서 uvicorn 서버를 직접 시작합니다.

uvicorn app:app --host "0.0.0.0" --port 8080


부록


  • Example project using this pattern
  • 좋은 웹페이지 즐겨찾기