簡體   English   中英

在 hy-lang 中使用 asyncio 功能時自動插入等待

[英]Auto insert await when asyncio function in hy-lang

下面的do/a宏可以在使用asyncio函數時自動插入await 下面還顯示了用法。

(import asyncio)
(import time)

(defmacro do/a [&rest code] 
  `(do ~@(lfor p code
                (if
                  (= (cut (str (first p)) -2) "/a")
                  `(await ~p)
                  p))))

(defmacro progn/a [&rest code]
  `(.run_until_complete (.get-event-loop asyncio )
     ((fn/a []
        (do/a ~@code)
        ))
     ))

(defn/a sleep_test/a [t]  
  (await (asyncio.sleep t))
  (print t)
  t)

(defn sleep_test [t]  
  (time.sleep t)
  (print t)
  t)

(progn/a
  (print 3)
  (await (sleep_test/a 3))
  (sleep_test/a 2) ;;can omit await
  (sleep_test 1) ;;auto swich by fn name 
  (+ 20 30)
  )

此宏通過函數名稱“/a”檢測異步函數。 最好使用asyncio.iscoroutinefunction來檢測異步函數。 但這不起作用。 請看下面的宏和執行結果。

(defmacro isasynctestmac [f]
  (if (asyncio.iscoroutinefunction f)
      `["async"  ~(asyncio.iscoroutinefunction f) (asyncio.iscoroutinefunction ~f) (type ~f)] 
      `["not async" ~(asyncio.iscoroutinefunction f) (asyncio.iscoroutinefunction ~f) (type ~f)] 
          ))

(isasynctestmac sleep_test/a)

==> ['not async', False, True, <class 'function'>]

你會看到一個 async 函數在 hy-lang 宏中被視為一個符號。 應用eval並不能避免這個問題。

如何解決這個問題?

宏在編譯時運行,一個變量是否持有協程只有在運行時才知道,所以需要在運行時調用iscoroutinefunction (asyncio.iscoroutinefunction f)在您的宏isasynctestmac僅檢查用作變量名稱的符號,而不是變量的值。 下面是如何使用iscoroutinefunction編寫do/a ,這里是代碼的其余部分,例如刪除了sleep_test的額外括號。 (將來,在發布到 Stack Overflow 之前,請確保您的代碼中應該已經可以工作的部分確實已經可以工作。)

(import asyncio time) 

(defmacro do/a [&rest code] 
  `(do ~@(lfor p code
    (if (and (instance? HyExpression p) p (!= (first p) (HySymbol "await")))
      `(if (asyncio.iscoroutinefunction ~(first p))
        (await ~p)
        ~p)
      p))))

(defmacro progn/a [&rest code]
  `(.run_until_complete (.get-event-loop asyncio)
    ((fn/a []
      (do/a ~@code)))))

(defn/a sleep_test/a [t]  
  (await (asyncio.sleep t))
  (print t)
  t)

(defn sleep_test [t]  
  (time.sleep t)
  (print t)
  t)

(print (progn/a
  (print 3)
  (await (sleep_test/a 3))
  (sleep_test/a 2)
  (sleep_test 1)
  (+ 20 30)))

@Kodiologist 顯示的方法存在以下問題。 以下 python 代碼有效。

import asyncio
import time
async def sleep_testa(t, hintfn):
    await asyncio.sleep(t) if asyncio.iscoroutinefunction(hintfn) else time.sleep(t)

但是在def之前刪除async后,程序停止並出現錯誤SyntaxError: invalid syntax

import asyncio
import time
def sleep_testa(t, hintfn):
    await asyncio.sleep(t) if asyncio.iscoroutinefunction(hintfn) else time.sleep(t)
==> SyntaxError: invalid syntax

動態切換異步和非異步代碼似乎是不可能的。 我們必須在宏展開之前切換異步和非異步代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM