[問題] 請問 Coroutine 怎麼解這個問題

看板Python作者 (吹笛牧童)時間1年前 (2023/02/05 12:58), 1年前編輯推噓2(207)
留言9則, 5人參與, 1年前最新討論串1/1
描述一下問題: 目前的工作我可以用 multi-thread 做到 https://paste.ee/p/0oAqf 執行結果: 03:16:44: do 1 notify 03:16:45: do 2 do 1 是 thread1 會動的證明,然後用 condition 塞住自己 notify 代表 thread2 利用 condition 通知 thread1 然後 do 2 代表 thread1 果然解鎖了,繼續執行 如果要改成用 Coroutine 做,我也做得到 https://paste.ee/p/BiPJp 結果是一模一樣的(除了時間不一樣) 注意到,和 multi-thread 的版本相比 condition 不能在全域的地方產生了 不然會有一個錯誤訊息,說是不能使用不同 loop 的東西 改用 Coroutine 寫也一樣,只是 condition 改用 asyncio 的版本 這還難不倒我,也算一想就通 因為它們不是真正的 thread 我知道 python 的 multi-thread 不算真正的 thread 但不影響我討論,對吧! 附上兩支程式,代表這程度我懂 接下來要談我不懂的 如果我在 task1 裡用 thead 版的 condition 把 task1 塞住 那 task2 也會一併塞住! 因為它們其實是同一個 thread 但我若用 asyncio 版本的 condition, 那所謂的塞住就只是交回控制權給 loop 而 loop 會再次分配給 task-2 以達到 Coroutine 的偽多工;完美~ https://paste.ee/p/U7nzP 這是用 thread 版本的 condition 把整個 Coroutine 塞住的例子 執行結果: 03:24:09: do 1 連 notify 都不會印出了,因為 task1 塞住,task2 根本就不會去執行 現在問題在,我的 task-2 若不是 async 宣告 這就是個問題,因為它本來是另一個 thread,打算改寫過來但不順利 這不是什麼簡單複雜化,而是我必需把專案的情境模擬成這樣 因為有某些部份是引用別人寫的 lib, 我不想去全面改寫 https://paste.ee/p/kgAsv 執行結果: 03:26:44: do 1 notify do 1 有印出,然後 task1 塞住 thread2 要求解鎖其實也做到了 注意到我的 thread2 是呼叫 asnyc 版本的 release() 要求是有要求,但 task1 不照辦,根本不會收到 notify!!!! 所以現在是 task-1 & thread-2 之間的 condition 控制問題了 難道我必需全面棄用 thread, 一定要把 thread-2 改寫成 task-2? 問題就在 condition.notify_all() 不會有預期的效果 但如果用 multi-thread, 我是輕易能做好這些事的 像這樣要怎麼讓 condition 正常的運作起來呢? 謝謝 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 123.204.157.162 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Python/M.1675573110.A.ED1.html 看到 queue 好像想到解法了 先在 task-2 裡建一個 asyncio 版本的 queue 然後 main-thread 可以把想做的事推進去 task-2 自己取出來就可以做了 來試試.. 失敗,因為這樣 main-thread 也必需改寫成 asyncio 版本 目前還是無解!! 需要附上程式嗎? ※ 編輯: HuangJC (123.204.157.162 臺灣), 02/05/2023 13:49:11

02/05 14:34, 1年前 , 1F
看不太懂你想要問什麼...
02/05 14:34, 1F
程式附上了,這個貼程式碼的空間真棒,免註冊 但好像放久一點就會消失了 XD 我已經找到'堪用'的解法了 就是在 task 中,多加一個 moniter task, 監視用 一秒一次監視狀況 如果狀況發生,就由 moniter task 代為發送我想要執行的指令 moniter task 是很浪費 cpu 效能的,但我也只寫得出這種東西了 https://paste.ee/p/mxM0q 本例中,task2 就是我所謂的 moniter task task 一定要位在同一個 loop,由根部往上長 (至少目前我只寫得出這種) 所以我只好先把 task2 寫出來 而我所謂的,non asnyc 與 asnyc 之間的介面 就是由 tellTask2 這個介面擔任 tellTask2 將被別人寫的模組用 call back 改變 而 task2 是 asnyc 版本的,它只好用 polling 的方式去檢查 不會即時,而且無法一次對一次 為了避免 polling 太過頻繁,我只好加入 sleep 一秒 爛架構,但有解決問題。

02/05 15:36, 1年前 , 2F
你進公司前都沒碰python嗎
02/05 15:36, 2F

02/05 15:36, 1年前 , 3F
公司也很敢給你什麼不會的弄主架構
02/05 15:36, 3F
謙虛的說,我 python 才學兩年 但 C 語言我有十年以上的底子 有新東西就學一下看能不能用 這時膨風更慘,會被人說都這麼資深了連這都不會 XD

02/05 16:02, 1年前 , 4F
epoll?
02/05 16:02, 4F
epoll 和我的問題完全是另一個維度了 就算 epoll 能解,我還是想要解目前的問題 我說過,這個問題我已經用不太好的方法解掉了;解得不漂亮 就算 epoll 能解,都不會是我心目中的漂亮 但產品不會有問題

02/05 16:09, 1年前 , 5F
Python的thread也不是真的multi啊 會有coroutine 就是
02/05 16:09, 5F

02/05 16:09, 1年前 , 6F
要改善cpu 使用效率問題
02/05 16:09, 6F

02/05 16:14, 1年前 , 7F
Async create_tash勒 我實在不知道你要幹嘛
02/05 16:14, 7F
我以為你說我打錯字,看來你是建議我用 create_task 我有用,不過當 call back 本身不是 asnyc 版本時,問題很難解決

02/05 18:49, 1年前 , 8F
簡單複雜化? 看不懂了 建議你重學os
02/05 18:49, 8F
請問要我學 os 的哪一章?os 很大,節省一下我的時間 ----------- 文章整個翻新過,附上我測試的程式了 ※ 編輯: HuangJC (123.204.157.162 臺灣), 02/06/2023 03:45:39

02/06 11:04, 1年前 , 9F
用asyncio.to_thread?
02/06 11:04, 9F
文章代碼(AID): #1ZtpTsxH (Python)
文章代碼(AID): #1ZtpTsxH (Python)