python上位机开发经验总结01
魔方机器人比赛中使用python写了上位机,总结一些经验待以后翻看。主要分4个方面,python变量与文件的处理,threading多线程模块使用经验,tkinter使用经验,其它零零碎碎的经验
python变量与文件的处理
主要是单文件内变量的处理经验与多文件内变量的处理经验。
全局变量与局部变量
python中的局部变量产生在函数内,在函数返回之后被释放,可以(但不建议)与全局变量同名。全局变量只能在模块(文件)级别使用,不能跨模块使用。
python中的全局变量在使用时有两个注意
- 全局变量需要在模块级别定义
- 在函数中修改全局变量时需要先用修饰词
global声明
当函数中没有对变量作global修饰时,有两种情况
- 函数中只对变量作读取操作,则可以直接读取在模块级别定义的同名变量
- 函数中对变量作了写(修改)操作,则认为此变量为局部变量,即使变量与模块级别定义的变量同名,也会新建局部变量而不会去修改同名变量
如以下的例子
flag = 1
def false_reset_flag():
flag = 0
def right_reset_flag():
global flag
flag = 0
false_reset_flag()
print(flag)
right_reset_flag()
print(flag)
以上程序的执行结果为
1
0
并且,把变量传入函数之后进行修改也是不可行的,python会将传入的变量复制作为局部参数。但是如果在程序中需要很多flag(标志变量),那么逐一定义并修改全局变量是非常不优雅的,我们可以采用传入实例,调用实例中的函数修改自己的变量的方法。终究,python还是面向对象的语言。如以下例子
flag = 1
class FlagClass(object):
def __init__(self):
self.flag = 1
def reset_flag(self):
self.flag = 0
def false_reset(x):
x = 0
def reset(x):
x.flag = 0
false_reset(flag)
print(flag)
flag_class = FlagClass()
reset(flag_class)
print(flag_class.flag)
以上程序的执行结果为
1
0
文件间的变量处理
上面其实已经提到了,python最优雅的编程方式是面向对象编程,模块(文件)间的处理也是一样。最好把每个模块中的东西全部封装成类,实现模块之间的解耦。但是有的时候(尤其是完成一个特定的算法和工作流程)面向过程的编程更为方便,这时候我们就需要去处理模块之间的很多flag(标志变量)了。
首先我们要明确一个核心思想:模块之间是不能相互写(修改)变量的。如果从其它模块import了某个变量,实际上是把这个变量复制过来,作为一个本模块内的“局部变量”。所以我们模块间修改变量的策略也是和封装成类差不多:把一个模块看成一个庞大的实体,在模块内定义修改自己变量的函数,在其它模块中调用这个函数。如以下例子
# module1.py
flag = 1
def reset_flag():
global flag
flag = 0
# 下面是需要调用的函数,里面会修改flag的值来标志有没有完成
......
# module2.py
from module1 import flag, reset_flag
print('flag')
if flag:
print('动作完成,重置标志')
reset_flag()
from module1 import flag
print('flag')
运行module2得到的结果如下
1
动作完成,重置标志
0
threading模块使用经验
threading是python提供的在底层的_threading基础上封装好的使用方便的多线程模块,但是这个模块并不太完善。
之所以说它使用方便,是因为它可以方便地创建线程,且线程中可以直接修改全局变量(像上面说的一样用global声明即可);说它不方便是因为它没有办法很好地管理线程(我的意思是很简单方便,有能力自己设计机制管理的大佬请忽略),如果你的线程中运行的是一个死循环,那么一旦线程开始,就处于失控状态,再也无法结束。
分享我本次使用threading模块的2个经验。
管理线程
下面是我在本次工程中管理线程的经验,虽然并不是一个非常优雅的方法,但是还算好用。核心思想是定义一个线程的flag,定义成全局变量还是定义在类里可以根据实际情况决定。把死循环改为一个带判断的while循环,那么结束线程时只需修改flag的值即可。如以下例子
class COM(object):
def __init__(self, port, baud):
self.port = port
self.baud = int(baud)
self.com = serial.Serial()
self.recvBuffer = Queue(maxsize=10)
self.__recv_running = True # 标志接收线程是否运行
self.recvThread = threading.Thread()
def open(self):
try:
self.com = serial.Serial(self.port, self.baud)
except Exception:
print('Open COM failed: {}'.format(self

本文分享了Python上位机开发的实际经验,包括变量管理、多线程应用、GUI设计等,特别介绍了tkinter和OpenCV的具体使用技巧。
最低0.47元/天 解锁文章
2万+





