记录python的线程和进程/keyboard/tkinter的几个问题(写贪吃蛇的总结)
写了个贪吃蛇,记录一点问题:
1. python进程之间的数据不共享,需要安全队列Queue来互通数据。队列使用multiprocessing的Queue,使用queue的Queue可能会有问题
2. python调用函数传参时,不能指定值传递还是引用。对象传递,函数内修改能直接修改对象的值(字典和列表也是对象传递),而数,元组,字符串等都是值传递。
3. global声明的全局变量对多线程(threading)有效。需要在子函数里声明使用全局变量,这个和C/C++声明全局变量方式有区别。但是对多进程(multiprocessing)无效。
输出结果为:任务A多线程正常执行,任务B多进程报错,报错类型是变量未定义,也就是没有使用全局变量
3. 定时器需要在定时函数内部再次调用定时函数。和ESP32的定时器逻辑不一样。
记录一下使用方法
这个函数的运行结果为:全局变量正常,效果是输出越来越快
4. keyboard的hook函数,函数默认传递了按键这个事件,通过name和event_type判断哪个键被按下,哪个键被抬起。按键事件是非阻塞的,每当有按键操作就会调用一次。程序会阻塞在wait处,直到等到想要的值。暂时不知道怎么传参,也不知道怎么返回参数。
5. keyboard的is_press函数,只能检测当前时刻按键是否处于按下状态。所以这个函数除了写在while的死循环里,实在想不出好用的方法。但是写在while循环里,按下一次就会被检测N此,导致有N多个输出。
所以我想了一下,开线程,然后用while检测,可以达到类似hook的效果,还能自定义传参和返回参数。
这样子的话,给每一个键都分配一个线程,自己只检测自己的事件,每一个按键按下和抬起互不干涉。可以通过安全队列Queue来同步这里面的消息。在按键按下或者抬起的时候可以调用其他函数来响应按键这个事件,而且这个可以自由传递参数。return的话还没思路,既然都用了多线程,那么直接global或者Queue解决吧。
6 tkinter:TK和mainloop之间不能使用while死循环来阻塞,可以用多线程/进程来解决。button,menu,Entry等等的控件在有操作的时候会调用回调函数,并且更新,但是canvas,lable不会主动的更新,需要执行update才可以。但是update不是实时更新所有控件,只有update被调用才会更新。所以感觉很矛盾,写while就运行不到mainloop,但是不写while吧,update不会一直被执行。之前也是,这个问题最终还是写了个定时任务来定时刷新。
7. tk生成的控件对象一定要指定布局,Frame也需要指定布局。不指定布局的控件始终不会被显示。
绝对布局:place(x=10, y=10),
相对布局:pack()
表格布局:grid(row=0, column=0)
8. tk生成的控件是有ID的,可以被销毁和删除。目前还不懂这个规则。itemconfig可以修改控件的属性,第一个参数是ID,其他参数是option。若canvas需要增量式的更新,用list记录新增的东西,使用canvas.delete(item)来删除时间久远的东西也是个不错的选择。
9. list的index方法会在没有找到内容的时候报错,可以用try except来经行异常处理。用法:list.index(tiem[, start, end]),可选则起始位置和结束位置。for循环遍历列表也能找到对应的内容。但是从效率上讲,比不上list的index方法。就算是前两项就能找到内容也拉不开时间差距,list越长,for循环的劣势越大。
10. isinstance(item,type)方法可以判断变量的类型。对列表内数据比较杂乱的东西可能有比较好的效果。