python上位机开发经验总结01

本文分享了Python上位机开发的实际经验,包括变量管理、多线程应用、GUI设计等,特别介绍了tkinter和OpenCV的具体使用技巧。

python上位机开发经验总结01

魔方机器人比赛中使用python写了上位机,总结一些经验待以后翻看。主要分4个方面,python变量与文件的处理,threading多线程模块使用经验,tkinter使用经验,其它零零碎碎的经验

python变量与文件的处理

主要是单文件内变量的处理经验与多文件内变量的处理经验。

全局变量与局部变量

python中的局部变量产生在函数内,在函数返回之后被释放,可以(但不建议)与全局变量同名。全局变量只能在模块(文件)级别使用,不能跨模块使用。

python中的全局变量在使用时有两个注意

  1. 全局变量需要在模块级别定义
  2. 在函数中修改全局变量时需要先用修饰词global声明

当函数中没有对变量作global修饰时,有两种情况

  1. 函数中只对变量作读取操作,则可以直接读取在模块级别定义的同名变量
  2. 函数中对变量作了写(修改)操作,则认为此变量为局部变量,即使变量与模块级别定义的变量同名,也会新建局部变量而不会去修改同名变量

如以下的例子

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
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值