最近在看 ayncio 這塊內容
因而打算從 asyncio.run 這個 函數做爲入口看下內部是如何工做的
下面是源碼以及一些分析python
若有問題, 歡迎交流linux
另外 有沒得大佬曉得 博客園的 markdown 怎麼顯示行號啊markdown
def run(main, *, debug=False): if events._get_running_loop() is not None: # 獲取當前是否含有 loop raise RuntimeError( "asyncio.run() cannot be called from a running event loop") if not coroutines.iscoroutine(main): # 判斷是不是一個 coroutine raise ValueError("a coroutine was expected, got {!r}".format(main)) loop = events.new_event_loop() # 獲取一個 loop """ 下面是獲取一個 loop 的邏輯 """ # get_event_loop_policy().new_event_loop() # 其中 get_event_loop_policy 是獲取 loop_policy # 在 linux 下 默認是使用 _UnixDefaultEventLoopPolicy # asyncio.unix_events._UnixDefaultEventLoopPolicy # loop 爲 _UnixSelectorEventLoop 的一個實例 # asyncio.unix_events._UnixSelectorEventLoop """ 獲取 loop end """ try: events.set_event_loop(loop) # get_event_loop_policy().set_event_loop(loop) """ get_event_loop_policy() -> _UnixDefaultEventLoopPolicy 一個實例 set_event_loop() # asyncio.events.BaseDefaultEventLoopPolicy#set_event_loop 給 loop_policy 設置 loop 放在 loop_policy 的 ThreadLocal 中 (引用變量) ps. 最近被引用變量坑的不行...有點怕(弱引用) """ loop.set_debug(debug) """ # todo 暫時不處理 """ return loop.run_until_complete(main) """ asyncio.base_events.BaseEventLoop#run_until_complete """ """如下是 run_until_complete 的邏輯""" def run_until_complete(self, future): self._check_closed() # 暫時無論 new_task = not futures.isfuture(future) # 判斷是不是 future toto task??? # todo asyncio.ensure_future asyncio.create_task 二者的差異 future = tasks.ensure_future(future, loop=self) # create task """ asyncio.tasks.ensure_future 看了下若是 future 是一個 coroutine 則會調用 create_task asyncio.base_events.BaseEventLoop#create_task # todo task 內容暫時不看 future 是 _asyncio.Task 或者是 _asyncio.Future -----asyncio.futures.Future(劃掉) Task 爲 Future 的一個子類 """ if new_task: # An exception is raised if the future didn't complete, so there # is no need to log the "destroy pending task" message future._log_destroy_pending = False future.add_done_callback(_run_until_complete_cb) """ add_done_callback 是寫在 so 文件中了 我並不知道他幹了點啥 ~~~~(>_<)~~~~ 可能相似這個吧: def add_done_callback(self, fn, *, context=None): '''Add a callback to be run when the future becomes done. The callback is called with a single argument - the future object. If the future is already done when this is called, the callback is scheduled with call_soon. ''' if self._state != _PENDING: self._loop.call_soon(fn, self, context=context) else: if context is None: context = contextvars.copy_context() """ # todo 有時間再看 try: self.run_forever() except: if new_task and future.done() and not future.cancelled(): # The coroutine raised a BaseException. Consume the exception # to not log a warning, the caller doesn't have access to the # local task. future.exception() raise finally: future.remove_done_callback(_run_until_complete_cb) if not future.done(): raise RuntimeError('Event loop stopped before Future completed.') return future.result() """-------- run_until_complete --------- end""" finally: try: _cancel_all_tasks(loop) loop.run_until_complete(loop.shutdown_asyncgens()) finally: events.set_event_loop(None) loop.close()