Python Socket TypeError: a bytes-like object is required, not 'str' 错误提示
《python核心编程》第三版,发现示例2-1代码返回错误…..纠结很久
发现这里python3.5和Python2.7在套接字返回值解码上有区别。
先介绍一下 python bytes和str两种类型转换的函数encode(),decode()
- str通过encode()方法可以编码为指定的bytes
- 反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法:
python核心编程书中的2-1例子
TCP服务器:
#coding=utf-8
#创建TCP服务器
from socket import *
from time import ctime
HOST=''
PORT=21567
BUFSIZ=1024
ADDR=(HOST,PORT)
tcpSerSock=socket(AF_INET,SOCK_STREAM) #创服务器套接字
tcpSerSock.bind(ADDR) #套接字与地址绑定
tcpSerSock.listen(5) #监听连接,传入连接请求的最大数
while True:
print('waiting for connection...')
tcpCliSock,addr =tcpSerSock.accept()
print('...connected from:',addr)
while True:
data =tcpCliSock.recv(BUFSIZ)
#print('date=',data)
if not data:
break
tcpCliSock.send(('[%s] %s' %(ctime(),data)))
tcpCliSock.close()
tcpSerSock.close()
TCP客户端
#coding=utf-8
from socket import *
HOST = 'localhost' # or 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR=(HOST,PORT)
tcpCliSock = socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)
while True:
data = input('> ')
print('data=',data);
if not data:
break
tcpCliSock.send(data)
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
print(data)
tcpCliSock.close()
返回的错误提示:
TypeError: a bytes-like object is required, not ‘str’
指的是18行tcpCliSock.send(data)
传入的参数是应该是bytes类型,而不是str类型。
于是我去百度,发现在StackOverflow上发现有人也出现同样的问题,并一个叫Scharron的人提出了解答:
In python 3, bytes strings and unicodestrings are now two different types. Since sockets are not aware of string encodings, they are using raw bytes strings, that have a slightly differentinterface from unicode strings.
So, now, whenever you have a unicode stringthat you need to use as a byte string, you need toencode() it. And whenyou have a byte string, you need to decode it to use it as a regular(python 2.x) string.
Unicode strings are quotes enclosedstrings. Bytes strings are b”” enclosed strings
When you use client_socket.send(data),replace it by client_socket.send(data.encode()). When you get datausing data = client_socket.recv(512), replace it by data =client_socket.recv(512).decode()
于是我去查python3.5的帮助手册。
socket.send(bytes[, flags])
Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Returns the number of bytes sent. Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data. For further information on this topic, consult the Socket Programming HOWTO.
Changed in version 3.5: If the system call is interrupted and the signal handler does not raise an exception, the method now retries the system call instead of raising an InterruptedError exception (see PEP 475 for the rationale).
socket.recv(bufsize[, flags])
Receive data from the socket. The return value is a bytes object representing the data received. The maximum amount of data to be received at once is specified by bufsize. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero.
Note
For best match with hardware and network realities, the value of bufsize should be a relatively small power of 2, for example, 4096.
Changed in version 3.5: If the system call is interrupted and the signal handler does not raise an exception, the method now retries the system call instead of raising an InterruptedError exception (see PEP 475 for the rationale).
修正后:
tcp服务器
#coding=utf-8
#创建TCP服务器
from socket import *
from time import ctime
HOST=''
PORT=21567
BUFSIZ=1024
ADDR=(HOST,PORT)
tcpSerSock=socket(AF_INET,SOCK_STREAM) #创服务器套接字
tcpSerSock.bind(ADDR) #套接字与地址绑定
tcpSerSock.listen(5) #监听连接,传入连接请求的最大数
while True:
print('waiting for connection...')
tcpCliSock,addr =tcpSerSock.accept()
print('...connected from:',addr)
while True:
data =tcpCliSock.recv(BUFSIZ).decode()
print('date=',data)
if not data:
break
tcpCliSock.send(('[%s] %s' %(ctime(),data)).encode())
tcpCliSock.close()
tcpSerSock.close()
tcp客户端:
#coding=utf-8
from socket import *
HOST = 'localhost' # or 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR=(HOST,PORT)
tcpCliSock = socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)
while True:
data = input('> ')
#print('data=',data);
if not data:
break
tcpCliSock.send(data.encode())
data = tcpCliSock.recv(BUFSIZ).decode()
if not data:
break
print(data)
tcpCliSock.close()
socket.sendto(bytes, address)
socket.sendto(bytes, flags, address)
Send data to the socket. The socket should not be connected to a remote socket, since the destination socket is specified by address. The optional flags argument has the same meaning as for recv() above. Return the number of bytes sent. (The format of address depends on the address family — see above.)
Changed in version 3.5: If the system call is interrupted and the signal handler does not raise an exception, the method now retries the system call instead of raising an InterruptedError exception (see PEP 475 for the rationale).
socket.recvfrom(bufsize[, flags])
Receive data from the socket. The return value is a pair (bytes, address) where bytes is a bytes object representing the data received and address is the address of the socket sending the data. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero. (The format of address depends on the address family — see above.)
同理修正udp服务器:
from socket import *
from time import ctime
HOST=''
PORT=21546
BUFSIZ=1024
ADDR=(HOST,PORT)
udpSerSock = socket(AF_INET,SOCK_DGRAM)
udpSerSock.bind(ADDR)
while True:
print('waiting for message...')
data,addr=udpSerSock.recvfrom(BUFSIZ)
data=data.decode()
udpSerSock.sendto(('[%s] %s'%(ctime(),data)).encode(),addr)
print('...received from and returned to:',addr)
udpSerSock.close()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏