__init__.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. r"""
  2. .. autofunction:: run_async
  3. .. autofunction:: run_asyncio_coroutine
  4. .. autofunction:: register_thread
  5. .. autofunction:: defer_call
  6. .. autoclass:: pywebio.session.coroutinebased.TaskHandle
  7. :members:
  8. """
  9. import threading
  10. from functools import wraps
  11. from .base import AbstractSession
  12. from .coroutinebased import CoroutineBasedSession
  13. from .threadbased import ThreadBasedSession, ScriptModeSession
  14. from ..exceptions import SessionNotFoundException
  15. from ..utils import iscoroutinefunction, isgeneratorfunction
  16. # 当前进程中正在使用的会话实现的列表
  17. _active_session_cls = []
  18. __all__ = ['run_async', 'run_asyncio_coroutine', 'register_thread']
  19. def register_session_implement_for_target(target_func):
  20. """根据target_func函数类型注册会话实现,并返回会话实现"""
  21. if iscoroutinefunction(target_func) or isgeneratorfunction(target_func):
  22. cls = CoroutineBasedSession
  23. else:
  24. cls = ThreadBasedSession
  25. if cls not in _active_session_cls:
  26. _active_session_cls.append(cls)
  27. return cls
  28. def get_session_implement():
  29. """获取当前会话实现。仅供内部实现使用。应在会话上下文中调用"""
  30. if not _active_session_cls:
  31. _active_session_cls.append(ScriptModeSession)
  32. _start_script_mode_server()
  33. # 当前正在使用的会话实现只有一个
  34. if len(_active_session_cls) == 1:
  35. return _active_session_cls[0]
  36. # 当前有多个正在使用的会话实现
  37. for cls in _active_session_cls:
  38. try:
  39. cls.get_current_session()
  40. return cls
  41. except SessionNotFoundException:
  42. pass
  43. raise SessionNotFoundException
  44. def _start_script_mode_server():
  45. from ..platform.tornado import start_server_in_current_thread_session
  46. start_server_in_current_thread_session()
  47. def get_current_session() -> "AbstractSession":
  48. return get_session_implement().get_current_session()
  49. def get_current_task_id():
  50. return get_session_implement().get_current_task_id()
  51. def check_session_impl(session_type):
  52. def decorator(func):
  53. @wraps(func)
  54. def inner(*args, **kwargs):
  55. curr_impl = get_session_implement()
  56. # Check if 'now_impl' is a derived from session_type or is the same class
  57. if not issubclass(curr_impl, session_type):
  58. func_name = getattr(func, '__name__', str(func))
  59. require = getattr(session_type, '__name__', str(session_type))
  60. curr = getattr(curr_impl, '__name__', str(curr_impl))
  61. raise RuntimeError("Only can invoke `{func_name:s}` in {require:s} context."
  62. " You are now in {curr:s} context".format(func_name=func_name, require=require,
  63. curr=curr))
  64. return func(*args, **kwargs)
  65. return inner
  66. return decorator
  67. @check_session_impl(CoroutineBasedSession)
  68. def run_async(coro_obj):
  69. """异步运行协程对象。协程中依然可以调用 PyWebIO 交互函数。 仅能在基于协程的会话上下文中调用
  70. :param coro_obj: 协程对象
  71. :return: An instance of `TaskHandle <pywebio.session.coroutinebased.TaskHandle>` is returned, which can be used later to close the task.
  72. """
  73. return get_current_session().run_async(coro_obj)
  74. @check_session_impl(CoroutineBasedSession)
  75. async def run_asyncio_coroutine(coro_obj):
  76. """若会话线程和运行事件的线程不是同一个线程,需要用 run_asyncio_coroutine 来运行asyncio中的协程。 仅能在基于协程的会话上下文中调用
  77. :param coro_obj: 协程对象
  78. """
  79. return await get_current_session().run_asyncio_coroutine(coro_obj)
  80. @check_session_impl(ThreadBasedSession)
  81. def register_thread(thread: threading.Thread):
  82. """注册线程,以便在线程内调用 PyWebIO 交互函数。仅能在基于线程的会话上下文中调用
  83. :param threading.Thread thread: 线程对象
  84. """
  85. return get_current_session().register_thread(thread)
  86. def defer_call(func):
  87. """设置会话结束时调用的函数。无论是用户主动关闭会话还是任务结束会话关闭,设置的函数都会被运行。
  88. 可以用于资源清理等工作。
  89. 在会话中可以多次调用 `defer_call()` ,会话结束后将会顺序执行设置的函数。
  90. :param func: 话结束时调用的函数
  91. """
  92. return get_current_session().defer_call(func)