Python中in运算符是否存在副作用?pySerial场景异常排查
问题原因及解决方案
核心原因:pySerial Serial类的__contains__魔法方法行为特殊
pySerial的Serial对象并没有把in运算符用来检查属性/方法是否存在,而是重载了__contains__方法,用于检测某个字节/字节串是否存在于串口接收缓冲区中。
当你执行"any" in self.serial_port时:
- Python会自动将字符串
"any"转换为字节串b'any'; - Serial的
__contains__方法会读取串口接收缓冲区中的所有数据,检查是否包含该字节串; - 关键是:这个读取操作会清空接收缓冲区(读取后不会将数据放回缓冲区),导致后续调用
serial_port.read(128)时已无数据可读,返回空字节数组。
而getattr(self.serial_port, "any", None)是直接检查对象是否存在名为any的属性/方法,不会触发__contains__,也就不会动接收缓冲区的数据,所以后续read能正常获取内容。
正确的检查方式
不要用in运算符来判断对象是否包含某个方法,改用以下标准方式:
- 使用
hasattr()直接检查方法存在性:if hasattr(self.serial_port, "any"): # 执行MicroPython UART相关逻辑(比如添加延迟) else: # 执行pySerial相关逻辑 - 或者用
getattr()做兜底检查:if getattr(self.serial_port, "any", None) is not None: # MicroPython UART逻辑 else: # pySerial逻辑
额外说明
MicroPython的UART对象没有重载__contains__方法,所以在MicroPython环境下"any" in uart会默认检查对象的属性列表,但这种方式本身就不是Python中检查属性存在的标准做法,标准做法始终是hasattr()或getattr()。
内容的提问来源于stack exchange,提问作者Simon A. Eugster
相关产品推荐
相关产品推荐

