看板 Python 關於我們 聯絡資訊
※ 引述《TakiDog (多奇狗)》之銘言: : 如果程式中出現threading(非Asyncio.run_in_executor)與Async混用 : 我一定會先思考人生,是不是把Python變難了,是不是能從流程改善 : 讓被歧視的膠水語言保有最後一點的優雅 一開始我就說,全用 thread 和 全用 Coroutine 我都做得到 但我有非得混用的理由,原因是我用了從網路下載的模組 它有它的 callback, 而 callback 不是我寫的,其宣告不帶有 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 callback;用說的就好 但看來只會被人說把問題變複雜了 問題是本來就複雜的,除非我去改寫 guizero 或許我真有本事改寫,畢竟它也附上 source code 但與其自己維護它,我傾向於不改它 題目就是 怎麼在 non async callback 中和已經存在的 Coroutine 互動 也有板友提及 epoll, 那我就不知 epoll 有沒有提供 async callback 了 或者得自己面對這個問題;那問題還是會回到同一點上 ※ 編輯: HuangJC (123.204.157.162 臺灣), 02/06/2023 13:17:45
zerof: GUI 的設計原本就是 event-based, 一定會有 callbacks ;你 02/06 13:32
zerof: 的問題多到我不知道該從何吐槽,最原始的問題你其實可以左 02/06 13:32
zerof: 轉 cython 學一下 release GIL 的用法就不會卡到 GUI (guiz 02/06 13:32
zerof: ero 底層是用 tk, written in C) 02/06 13:32
我也可以用 multi-process 而不是 thread 來解啊 解法不只一種,而且我不認為問題出在 GIL 畢竟我的 thread 有三十多個,我也真嫌多了 用了 Coroutine 就合併回一個,但卻是三十多個 task 我覺得這也蠻好的 Coroutine 既然是個潮流就來了解一下,有別的解法就先放一邊吧.. 真要 C 我何不回 C 的世界,寫純 C..
surimodo: 你python版本用多少 02/06 13:36
3.7, 前一篇有人回我 asyncio.to_thread 這應該是個解,但要 3.9 而它的底層我猜就是 loop.run_in_executo,這應該是同一回事 我目前正在了解 takidog 的邏輯,他那程式是跑起來了 我看能不能擺進 guizero 的 callback 框架裡 await asyncio.gather(job1, job2) 這句可能會出問題,因為真的把 guizero 的例子附上後 我不知要在哪裡 gather 它。。。 我非得拆散他們不可? XD
lycantrope: to_thread就是run_in_executor 02/06 14:26
https://paste.ee/p/HzTH3 這是較為完整的例子 包含了程式的退出(之前只為了測試某些目的,程式有 bug 無法結束都不管) 結果我還是只能用 polling 寫出來 因為我無法把該 gather 在一起的東西拆開! 至於全域變數的使用,傳送。。。 暴力點,用 class 就好 XD 我也試過把整個 main 宣告為 async,讓它當我 Coroutine 的根部 但是失敗了 ※ 編輯: HuangJC (123.204.157.162 臺灣), 02/06/2023 16:13:45
poototo: https://paste.ee/p/4EsOS 02/06 23:30
poototo: 以上連結是使用兩種condition 02/06 23:32
poototo: asyncio.condition是基於asyncio.event 02/06 23:33
poototo: asynio.notify跨緒僅可解鎖及廣播同eventloop的waiter 02/06 23:36
poototo: loop向下對task,向上對thread,越級對其他loop的task 02/06 23:53
poototo: 我不確定可行性,但異步管理弄太複雜我寧願犧牲效能... 02/06 23:55
我就是這樣做,但你這個例子也無法搬至 guizero 上 我前面有想搬 TakiDog 的例子,但發現無法找到 gather 的點 搬至 guizero 後我是要做到 UI 互動 也就是 task 1 要是個 loop 不斷跑 而 sync func 是由螢幕上的按鍵經使用者互動,guizero 會 callback 每 callback 一次,task 1 的 loop 就解鎖 condition 跑一次 do 1, do2, ..... 你的例子,t_cond 不在 task1a 裡,所以 task1a 不是早就執行起來等 也不會是每經 t_cond callback 一次,task1a 就繞一次 稍微改一下就是我後來的解法了
OnoderaHaru: https://paste.ee/p/HMP2T#s=0 02/07 01:00
OnoderaHaru: 反正最後還是包裝成執行緒,直接用執行緒可以用的來 02/07 01:04
OnoderaHaru: 溝通 02/07 01:04
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 才有意義 其實我在前面的討論裡都有提及這些,只是文筆不好,無法讓大家理解這個意思 但現在這篇應該能解釋了(我回去修文改成紅色的部份)
OnoderaHaru: https://paste.ee/p/HMP2T#s=1 (執行緒和協程溝通) 02/07 01:06
這個可以 XD 那我就是想法子利用這個 queue 去湊架構了... 剛草草看了底層 source code 不很清楚它怎麼做到 sync async 轉換的 ---- 這一面貼兩個程式我不會,是不是因為我沒註冊 XD ※ 編輯: HuangJC (1.168.18.180 臺灣), 02/08/2023 13:38:59 ※ 編輯: HuangJC (116.241.233.114 臺灣), 03/04/2023 03:36:10