記錄python的線程和進程/keyboard/tkinter的幾個問題(寫貪吃蛇的總結(jié))
寫了個貪吃蛇,記錄一點問題:
????1.????python進程之間的數(shù)據(jù)不共享,需要安全隊列Queue來互通數(shù)據(jù)。隊列使用multiprocessing的Queue,使用queue的Queue可能會有問題
????2.????python調(diào)用函數(shù)傳參時,不能指定值傳遞還是引用。對象傳遞,函數(shù)內(nèi)修改能直接修改對象的值(字典和列表也是對象傳遞),而數(shù),元組,字符串等都是值傳遞。
????3.????global聲明的全局變量對多線程(threading)有效。需要在子函數(shù)里聲明使用全局變量,這個和C/C++聲明全局變量方式有區(qū)別。但是對多進程(multiprocessing)無效。
????輸出結(jié)果為:任務A多線程正常執(zhí)行,任務B多進程報錯,報錯類型是變量未定義,也就是沒有使用全局變量
? ??
3.????定時器需要在定時函數(shù)內(nèi)部再次調(diào)用定時函數(shù)。和ESP32的定時器邏輯不一樣。
記錄一下使用方法
? ?????這個函數(shù)的運行結(jié)果為:全局變量正常,效果是輸出越來越快
4.????keyboard的hook函數(shù),函數(shù)默認傳遞了按鍵這個事件,通過name和event_type判斷哪個鍵被按下,哪個鍵被抬起。按鍵事件是非阻塞的,每當有按鍵操作就會調(diào)用一次。程序會阻塞在wait處,直到等到想要的值。暫時不知道怎么傳參,也不知道怎么返回參數(shù)。
5.????keyboard的is_press函數(shù),只能檢測當前時刻按鍵是否處于按下狀態(tài)。所以這個函數(shù)除了寫在while的死循環(huán)里,實在想不出好用的方法。但是寫在while循環(huán)里,按下一次就會被檢測N此,導致有N多個輸出。
????所以我想了一下,開線程,然后用while檢測,可以達到類似hook的效果,還能自定義傳參和返回參數(shù)。
????這樣子的話,給每一個鍵都分配一個線程,自己只檢測自己的事件,每一個按鍵按下和抬起互不干涉。可以通過安全隊列Queue來同步這里面的消息。在按鍵按下或者抬起的時候可以調(diào)用其他函數(shù)來響應按鍵這個事件,而且這個可以自由傳遞參數(shù)。return的話還沒思路,既然都用了多線程,那么直接global或者Queue解決吧。
6 ????tkinter:TK和mainloop之間不能使用while死循環(huán)來阻塞,可以用多線程/進程來解決。button,menu,Entry等等的控件在有操作的時候會調(diào)用回調(diào)函數(shù),并且更新,但是canvas,lable不會主動的更新,需要執(zhí)行update才可以。但是update不是實時更新所有控件,只有update被調(diào)用才會更新。所以感覺很矛盾,寫while就運行不到mainloop,但是不寫while吧,update不會一直被執(zhí)行。之前也是,這個問題最終還是寫了個定時任務來定時刷新。
7.????tk生成的控件對象一定要指定布局,F(xiàn)rame也需要指定布局。不指定布局的控件始終不會被顯示。
????????絕對布局:place(x=10, y=10),
????????相對布局:pack()
????????表格布局:grid(row=0, column=0)
8.????tk生成的控件是有ID的,可以被銷毀和刪除。目前還不懂這個規(guī)則。itemconfig可以修改控件的屬性,第一個參數(shù)是ID,其他參數(shù)是option。若canvas需要增量式的更新,用list記錄新增的東西,使用canvas.delete(item)來刪除時間久遠的東西也是個不錯的選擇。
9.? list的index方法會在沒有找到內(nèi)容的時候報錯,可以用try except來經(jīng)行異常處理。用法:list.index(tiem[, start, end]),可選則起始位置和結(jié)束位置。for循環(huán)遍歷列表也能找到對應的內(nèi)容。但是從效率上講,比不上list的index方法。就算是前兩項就能找到內(nèi)容也拉不開時間差距,list越長,for循環(huán)的劣勢越大。
10.????isinstance(item,type)方法可以判斷變量的類型。對列表內(nèi)數(shù)據(jù)比較雜亂的東西可能有比較好的效果。