__init__.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. r"""
  2. .. autofunction:: run_async
  3. .. autofunction:: run_asyncio_coroutine
  4. .. autofunction:: register_thread
  5. .. autoclass:: pywebio.session.coroutinebased.TaskHandle
  6. :members:
  7. """
  8. import asyncio
  9. import inspect
  10. import threading
  11. from functools import wraps
  12. from .base import AbstractSession
  13. from .coroutinebased import CoroutineBasedSession
  14. from .threadbased import ThreadBasedSession, ScriptModeSession
  15. from ..exceptions import SessionNotFoundException
  16. _session_type = None
  17. __all__ = ['run_async', 'run_asyncio_coroutine', 'register_thread']
  18. def set_session_implement_for_target(target_func):
  19. """根据target_func函数类型设置会话实现"""
  20. global _session_type
  21. if asyncio.iscoroutinefunction(target_func) or inspect.isgeneratorfunction(target_func):
  22. _session_type = CoroutineBasedSession
  23. else:
  24. _session_type = ThreadBasedSession
  25. def get_session_implement():
  26. global _session_type
  27. if _session_type is None:
  28. _session_type = ScriptModeSession
  29. _start_script_mode_server()
  30. return _session_type
  31. def _start_script_mode_server():
  32. from ..platform.tornado import start_server_in_current_thread_session
  33. start_server_in_current_thread_session()
  34. def get_current_session() -> "AbstractSession":
  35. return get_session_implement().get_current_session()
  36. def get_current_task_id():
  37. return get_session_implement().get_current_task_id()
  38. def check_session_impl(session_type):
  39. def decorator(func):
  40. @wraps(func)
  41. def inner(*args, **kwargs):
  42. now_impl = get_session_implement()
  43. if not issubclass(now_impl,
  44. session_type): # Check if 'now_impl' is a derived from session_type or is the same class
  45. func_name = getattr(func, '__name__', str(func))
  46. require = getattr(session_type, '__name__', str(session_type))
  47. now = getattr(now_impl, '__name__', str(now_impl))
  48. raise RuntimeError("Only can invoke `{func_name:s}` in {require:s} context."
  49. " You are now in {now:s} context".format(func_name=func_name, require=require,
  50. now=now))
  51. return func(*args, **kwargs)
  52. return inner
  53. return decorator
  54. @check_session_impl(CoroutineBasedSession)
  55. def run_async(coro_obj):
  56. """异步运行协程对象。协程中依然可以调用 PyWebIO 交互函数。 仅能在 CoroutineBasedSession 会话上下文中调用
  57. :param coro_obj: 协程对象
  58. :return: An instance of `TaskHandle <pywebio.session.coroutinebased.TaskHandle>` is returned, which can be used later to close the task.
  59. """
  60. return get_current_session().run_async(coro_obj)
  61. @check_session_impl(CoroutineBasedSession)
  62. async def run_asyncio_coroutine(coro_obj):
  63. """若会话线程和运行事件的线程不是同一个线程,需要用 run_asyncio_coroutine 来运行asyncio中的协程
  64. :param coro_obj: 协程对象
  65. """
  66. return await get_current_session().run_asyncio_coroutine(coro_obj)
  67. @check_session_impl(ThreadBasedSession)
  68. def register_thread(thread: threading.Thread):
  69. """注册线程,以便在线程内调用 PyWebIO 交互函数。仅能在 ThreadBasedSession 会话上下文中调用
  70. :param threading.Thread thread: 线程对象
  71. """
  72. return get_current_session().register_thread(thread)