1
0

__init__.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import threading
  2. from functools import wraps
  3. from .asyncbased import AsyncBasedSession
  4. from .base import AbstractSession
  5. from .threadbased import ThreadBasedWebIOSession, DesignatedThreadSession
  6. from ..exceptions import SessionNotFoundException
  7. _session_type = ThreadBasedWebIOSession
  8. __all__ = ['set_session_implement', 'run_async', 'run_asyncio_coroutine', 'register_thread']
  9. _server_started = False
  10. def mark_server_started():
  11. """标记服务端已经启动"""
  12. global _server_started
  13. _server_started = True
  14. def set_session_implement(session_type):
  15. global _session_type
  16. assert session_type in [ThreadBasedWebIOSession, AsyncBasedSession, DesignatedThreadSession]
  17. _session_type = session_type
  18. def get_session_implement():
  19. global _session_type
  20. return _session_type
  21. def _start_script_mode_server():
  22. from ..platform import start_server_in_current_thread_session
  23. set_session_implement(DesignatedThreadSession)
  24. start_server_in_current_thread_session()
  25. def get_current_session() -> "AbstractSession":
  26. try:
  27. return _session_type.get_current_session()
  28. except SessionNotFoundException:
  29. if _server_started:
  30. raise
  31. # 没有显式启动backend server时,在当前线程上下文作为session启动backend server
  32. _start_script_mode_server()
  33. return _session_type.get_current_session()
  34. def get_current_task_id():
  35. try:
  36. return _session_type.get_current_task_id()
  37. except RuntimeError:
  38. if _server_started:
  39. raise
  40. # 没有显式启动backend server时,在当前线程上下文作为session启动backend server
  41. _start_script_mode_server()
  42. return _session_type.get_current_task_id()
  43. def check_session_impl(session_type):
  44. def decorator(func):
  45. @wraps(func)
  46. def inner(*args, **kwargs):
  47. now_impl = get_session_implement()
  48. if not issubclass(now_impl,
  49. session_type): # Check if 'now_impl' is a derived from session_type or is the same class
  50. func_name = getattr(func, '__name__', str(func))
  51. require = getattr(session_type, '__name__', str(session_type))
  52. now = getattr(now_impl, '__name__', str(now_impl))
  53. raise RuntimeError("Only can invoke `{func_name:s}` in {require:s} context."
  54. " You are now in {now:s} context".format(func_name=func_name, require=require,
  55. now=now))
  56. return func(*args, **kwargs)
  57. return inner
  58. return decorator
  59. @check_session_impl(AsyncBasedSession)
  60. def run_async(coro_obj):
  61. """异步运行协程对象,协程中依然可以调用 PyWebIO 交互函数。 仅能在 AsyncBasedSession 会话上下文中调用
  62. :param coro_obj: 协程对象
  63. """
  64. AsyncBasedSession.get_current_session().run_async(coro_obj)
  65. @check_session_impl(AsyncBasedSession)
  66. async def run_asyncio_coroutine(coro_obj):
  67. """若会话线程和运行事件的线程不是同一个线程,需要用 run_asyncio_coroutine 来运行asyncio中的协程
  68. :param coro_obj: 协程对象
  69. """
  70. return await AsyncBasedSession.get_current_session().run_asyncio_coroutine(coro_obj)
  71. @check_session_impl(ThreadBasedWebIOSession)
  72. def register_thread(thread: threading.Thread, as_daemon=True):
  73. """注册线程,以便在线程内调用 PyWebIO 交互函数。仅能在 ThreadBasedWebIOSession 会话上下文中调用
  74. :param threading.Thread thread: 线程对象
  75. :param bool as_daemon: 是否将线程设置为 daemon 线程. 默认为 True
  76. """
  77. return ThreadBasedWebIOSession.get_current_session().register_thread(thread, as_daemon=as_daemon)