
本文详解如何在 Python 中安全、准确地构造包含十六进制转义序列(如 1)的字符串,并通过 serial.Serial 发送原始字节数据,避免因字符串转义错误导致串口通信失败。
本文详解如何在 python 中安全、准确地构造包含十六进制转义序列(如 `1`)的字符串,并通过 `serial.serial` 发送原始字节数据,避免因字符串转义错误导致串口通信失败。
在 Python 串口通信开发中,一个常见误区是混淆「字符串字面量」与「运行时字节序列」。例如,用户希望生成字符串 "123"(即字节 0x31, 0x32, 0x33,对应 ASCII 字符 '1', '2', '3'),却误写为:
hex_str = ''
for i in '123':
hex_str += '' + i # ❌ 错误:'' 不是合法转义,Python 解析报错或行为异常该写法会触发 SyntaxError: invalid x escape,因为 x 后必须紧跟两个十六进制数字(如 1),而 不完整。
✅ 正确做法:用原始字符串或字节构造,而非拼接转义字面量
若目标是动态生成形如 "\x31\x32\x33" 的字符串字面量表示(即包含反斜杠和 x 的纯文本),需对反斜杠进行双重转义(\ 表示单个 字符):
hex_str = ''
for i in '123':
hex_str += '\x3' + i # ✅ 正确:生成字符串 "\x31\x32\x33"
print(hex_str) # 输出:123(注意:这只是文本,不是实际字节!)⚠️ 但请注意:此结果是长度为 12 的字符串(含字符 '', 'x', '3', '1' 等),并非你真正需要发送给串口的 3 字节数据 b'123'。直接 ser.write(hex_str) 会发送 ASCII 编码的反斜杠文本,而非二进制指令。
立即学习“Python免费学习笔记(深入)”;
✅ 推荐方案:直接构造 bytes 对象(最安全、最高效)
应绕过字符串转义,直接以整数或十六进制字面量构建 bytes:
# 方案 1:从字符串数字推导 ASCII 字节(推荐)
data = b''
for char in '123':
data += bytes([ord(char)]) # ord('1') → 49 → b'1'
# 或更简洁:
data = b''.join(bytes([ord(c)]) for c in '123')
# 方案 2:显式十六进制构造(适合任意 hex 值)
data = bytes([0x31, 0x32, 0x33])
# 方案 3:使用 bytes.fromhex()(输入为十六进制字符串,无空格)
data = bytes.fromhex('313233') # 注意:'313233' 是连续 hex 字符串? 完整合规的串口写入示例
import serial
ser = serial.Serial('/dev/tty.usbserial-FTCHMFWZ', 115200, timeout=1)
try:
# 构造完整协议帧:STX(0x02) + CMD(0x08) + DATA(b'123') + ETX(0x03)
payload = b'' + b'123' + b''
# 发送(确保传入 bytes 类型)
ser.write(payload)
ser.write(b'') # EOT
# 验证:打印实际发送的字节(十六进制格式)
print("Sent bytes:", payload.hex()) # 输出:020831323303
finally:
ser.close()⚠️ 关键注意事项
- 永远不要对 serial.write() 传入 str:ser.write() 要求 bytes 或 bytearray;传入 str(如 '1')在 Python 3 中会引发 TypeError。
- xHH 是编译期转义,非运行时解析:'1' 在代码中即被解释为单字节 b'1';而 '\x31' 是 4 字节字符串 b'\x31'。
- 调试技巧:用 .hex() 方法查看实际字节内容,例如 b'12'.hex() → '3132'。
- 协议兼容性:确认设备期望的是 ASCII 字符 '1'(0x31)还是数值 1(0x01)——二者完全不同。
掌握 bytes 的构造逻辑,而非依赖字符串转义拼接,是可靠实现串口二进制通信的基础。










