Re: [問題] 請問 Coroutine & 一般 callback 合作的問題

看板Python作者 (吹笛牧童)時間1年前 (2023/02/06 12:28), 1年前編輯推噓5(5011)
留言16則, 5人參與, 1年前最新討論串2/4 (看更多)
※ 引述《TakiDog (多奇狗)》之銘言: : 如果程式中出現threading(非Asyncio.run_in_executor)與Async混用 : 我一定會先思考人生,是不是把Python變難了,是不是能從流程改善 : 讓被歧視的膠水語言保有最後一點的優雅 一開始我就說,全用 thread 和 全用 Coroutine 我都做得到 但我有非得混用的理由,原因是我用了從網路下載的模組 它有它的 call back, 而 call back 不是我寫的,其宣告不帶有 async 至於流程 work around 我也做到了,但感覺像 polling 問題在這裡不好 : > https://paste.ee/p/kgAsv : 在同一個process中任意執行 asyncio.run 並不一定是同一個eventLoop : (不同thread又分別建立了Loop) 這我是知道的 : 在整個process中 asyncio.run 基本上只應該存在一個 我以為,不同 thread 可以各別有 asyncio.run : 你可以嘗試把asyncio.run的部分都改用 loop = get_event_loop() : 查看loop的id. 或從Debugger查看 : --- : 我嘗試在你最後的code中修改,在同一個process存在2個loop : 又希望不同的loop之間可以通知,感覺上就不太正確。 就是要想法子只有一個 loop 在 thread1 中把 loop 取出來 在 thread2 中,利用這個 loop 想要通知它 我也試過這種 其實一開始因為我沒找到貼 code 的方法,我試圖只用文字說明,我以為這可以 因為其實邏輯概念是跨語言的 multi-thread 在 C 有,在 python 也有;雖然不一樣,但不影響這個例子 Coroutine 在 C 我沒用過,但我相信也有實踐其概念的方法 所以我說明了一下,然後得到我必需重讀 OS 的評語 我不介意重讀,因為總是輸人一步 但我介意的是時間的分配,我可能必需趕快學別的東西,而不是成為 OS 專家。。 或者有人為了和我談 python 的 multi-thread 不是真的這件事 而把話題扯遠了(那豈不是專注在我文章中的任何漏洞,而不在文章的總體概念?) : :https://gist.github.com/takidog/c53f73e24295d66c76b5e330940bcf73 : 可以把loop, condition當作arg傳入,或是當作global : (我認為都非常的糟糕) 只要能解,都可能比我原本的解法好 本來 loop 是在高階 Coroutine 不用見到的東西 但碰到 bug 可能就要從低階去解 : > 因為有某些部份是引用別人寫的 lib, 我不想去全面改寫 : :run_in_executor : 我的理解可能也有錯誤,歡迎討論 附上程式 可以更好的形容為什麼我用了別人的東西, 而別人沒 async 的 callback 我為何不能改寫 https://paste.ee/p/Jvrxb 框架是這樣,註解在程式裡 本來不想列成這樣是因為還要麻煩板友安裝 guizero 一堆人都在用 PyQt,可能會覺得這個冷門 所以我就想:反正就是要交代我得有 non async call back;用說的就好 但看來只會被人說把問題變複雜了 問題是本來就複雜的,除非我去改寫 guizero 或許我真有本事改寫,畢竟它也附上 source code 但與其自己維護它,我傾向於不改它 題目就是 怎麼在 non async callback 中和已經存在的 Coroutine 互動 也有板友提及 epoll, 那我就不知 epoll 有沒有提供 async call back 了 或者得自己面對這個問題;那問題還是會回到同一點上 ※ 編輯: HuangJC (123.204.157.162 臺灣), 02/06/2023 13:17:45

02/06 13:32, 1年前 , 1F
GUI 的設計原本就是 event-based, 一定會有 callbacks ;你
02/06 13:32, 1F

02/06 13:32, 1年前 , 2F
的問題多到我不知道該從何吐槽,最原始的問題你其實可以左
02/06 13:32, 2F

02/06 13:32, 1年前 , 3F
轉 cython 學一下 release GIL 的用法就不會卡到 GUI (guiz
02/06 13:32, 3F

02/06 13:32, 1年前 , 4F
ero 底層是用 tk, written in C)
02/06 13:32, 4F
我也可以用 multi-process 而不是 thread 來解啊 解法不只一種,而且我不認為問題出在 GIL 畢竟我的 thread 有三十多個,我也真嫌多了 用了 Coroutine 就合併回一個,但卻是三十多個 task 我覺得這也蠻好的 Coroutine 既然是個潮流就來了解一下,有別的解法就先放一邊吧.. 真要 C 我何不回 C 的世界,寫純 C..

02/06 13:36, 1年前 , 5F
你python版本用多少
02/06 13:36, 5F
3.7, 前一篇有人回我 asyncio.to_thread 這應該是個解,但要 3.9 而它的底層我猜就是 loop.run_in_executo,這應該是同一回事 我目前正在了解 takidog 的邏輯,他那程式是跑起來了 我看能不能擺進 guizero 的 call back 框架裡 await asyncio.gather(job1, job2) 這句可能會出問題,因為真的把 guizero 的例子附上後 我不知要在哪裡 gather 它。。。 我非得拆散他們不可? XD

02/06 14:26, 1年前 , 6F
to_thread就是run_in_executor
02/06 14:26, 6F
https://paste.ee/p/HzTH3 這是較為完整的例子 包含了程式的退出(之前只為了測試某些目的,程式有 bug 無法結束都不管) 結果我還是只能用 polling 寫出來 因為我無法把該 gather 在一起的東西拆開! 至於全域變數的使用,傳送。。。 暴力點,用 class 就好 XD 我也試過把整個 main 宣告為 async,讓它當我 Coroutine 的根部 但是失敗了 ※ 編輯: HuangJC (123.204.157.162 臺灣), 02/06/2023 16:13:45

02/06 23:30, 1年前 , 7F

02/06 23:32, 1年前 , 8F
以上連結是使用兩種condition
02/06 23:32, 8F

02/06 23:33, 1年前 , 9F
asyncio.condition是基於asyncio.event
02/06 23:33, 9F

02/06 23:36, 1年前 , 10F
asynio.notify跨緒僅可解鎖及廣播同eventloop的waiter
02/06 23:36, 10F

02/06 23:53, 1年前 , 11F
loop向下對task,向上對thread,越級對其他loop的task
02/06 23:53, 11F

02/06 23:55, 1年前 , 12F
我不確定可行性,但異步管理弄太複雜我寧願犧牲效能...
02/06 23:55, 12F
我就是這樣做,但你這個例子也無法搬至 guizero 上 我前面有想搬 TakiDog 的例子,但發現無法找到 gather 的點 搬至 guizero 後我是要做到 UI 互動 也就是 task 1 要是個 loop 不斷跑 而 sync func 是由螢幕上的按鍵經使用者互動,guizero 會 call back 每 call back 一次,task 1 的 loop 就解鎖 condition 跑一次 do 1, do2, ..... 你的例子,t_cond 不在 task1a 裡,所以 task1a 不是早就執行起來等 也不會是每經 t_cond call back 一次,task1a 就繞一次 稍微改一下就是我後來的解法了

02/07 01:00, 1年前 , 13F

02/07 01:04, 1年前 , 14F
反正最後還是包裝成執行緒,直接用執行緒可以用的來
02/07 01:04, 14F

02/07 01:04, 1年前 , 15F
溝通
02/07 01:04, 15F
https://paste.ee/p/OxGNI 這會有問題 我把 reportTask 再進一步弄成 reportTask1, reportTask2 其中 reportTask2 就是無腦一直 looping 運作良好 然後把 self.q.get() 那行 unmark 就會發現問題 threading 的 queue (或任何同步物件) 它是阻塞一整個 queue 因為所有的 task 事實上是同一個 thread,所以一個塞住其他就塞住了 這就是要改用 asyny 版本的 queue 的原因 任何的阻塞,不管是 condition, lock, sleep 只要是 async 版本的,就能把執行權轉移到其他 task 上去 這樣使用 Coroutine 的 task 才有意義 其實我在前面的討論裡都有提及這些,只是文筆不好,無法讓大家理解這個意思 但現在這篇應該能解釋了(我回去修文改成紅色的部份)

02/07 01:06, 1年前 , 16F
https://paste.ee/p/HMP2T#s=1 (執行緒和協程溝通)
02/07 01:06, 16F
這個可以 XD 那我就是想法子利用這個 queue 去湊架構了... 剛草草看了底層 source code 不很清楚它怎麼做到 sync async 轉換的 ---- 這一面貼兩個程式我不會,是不是因為我沒註冊 XD ※ 編輯: HuangJC (1.168.18.180 臺灣), 02/08/2023 13:38:59
文章代碼(AID): #1Zu87ewq (Python)
文章代碼(AID): #1Zu87ewq (Python)