TypeError:需要一个类似字节的对象,而不是“str”

Posted

技术标签:

【中文标题】TypeError:需要一个类似字节的对象,而不是“str”【英文标题】:TypeError: a bytes-like object is required, not 'str' 【发布时间】:2016-01-05 08:24:08 【问题描述】:

以下是尝试使用套接字修改用户提供的输入的代码:

from socket import *

serverName = '127.0.0.1'
serverPort = 12000
clientSocket = socket(AF_INET, SOCK_DGRAM)
message = input('Input lowercase sentence:')
clientSocket.sendto(message,(serverName, serverPort))
modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
print (modifiedMessage)
clientSocket.close()

当我执行它并提供输入时,会发生以下错误:

Input lowercase sentence:fdsgfdf
Traceback (most recent call last):
  File "C:\srinath files\NETWORKS\UDPclient.py", line 6, in <module>
    clientSocket.sendto(message,(serverName, serverPort))
TypeError: a bytes-like object is required, not 'str'

我能做些什么来解决这个问题?

【问题讨论】:

第一个参数 (message) 必须是字节,但您传递的是一个字符串。您应该在发送之前对其进行编码,例如message.encode('utf-8') 但问题是我需要将字符串传递给服务器而不是字节 from socket import * serverName = 'hostname' serverPort = 12000 clientSocket = socket(AF_INET, SOCK_DGRAM) message = input('输入小写句子:') message.encode('utf-8') clientSocket .sendto(message,(serverName, serverPort)) modifiedMessage, serverAddress = clientSocket.recvfrom(2048) print (modifiedMessage) clientSocket.close() 网络上的东西是总是字节。服务器需要能够以某种方式理解这些字节。 那是因为message 仍然是一个字符串。你需要类似clientSocket.sendto(message.encode('utf-8'), ...) 【参考方案1】:

此代码适用于 Python 2。但在 Python 3 中,会导致位编码错误。我试图制作一个简单的 TCP 服务器并遇到了同样的问题。编码解决了这个问题。用sendto 命令试试这个。

clientSocket.sendto(message.encode(),(serverName, serverPort))

同样,如果您想完全按照发送的方式打印数据,您应该使用.decode() 在 UDP 服务器端接收数据。

【讨论】:

连接两端的编码和解码会增加延迟吗?如果是这样,python2 在发送数据方面实际上会比 python3 更快 在我看来,这不会影响延迟等性能。但是,我自己没有尝试过,所以我不能确定。 python 这样做是否只是为了在其原生 String 类中支持表情符号??我想对国际化有好处:message.encode('utf-16') 和?【参考方案2】:

编码和解码在 Python 3 中可以解决这个问题:

客户端:

>>> host='127.0.0.1'
>>> port=1337
>>> import socket
>>> s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
>>> s.connect((host,port))
>>> st='connection done'
>>> byt=st.encode()
>>> s.send(byt)
15
>>>

服务器端:

>>> host=''
>>> port=1337
>>> import socket
>>> s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
>>> s.bind((host,port))
>>> s.listen(1)
>>> conn ,addr=s.accept()
>>> data=conn.recv(2000)
>>> data.decode()
'connection done'
>>>

【讨论】:

另请参阅nedbatchelder.com/text/unipain.html 以了解为什么这在 Python 3 中发生了变化。【参考方案3】:

当您遇到此消息的错误时使用my_string.encode()

(其中my_string 是您传递给函数/方法的字符串)。

str 对象的encode 方法将字符串的编码版本作为bytes object 返回,然后您可以使用它。 在这个特定的实例中,套接字方法such as .send 需要一个字节对象作为要发送的数据,不是一个字符串对象

由于您有一个 str 类型的对象,并且您将它传递给一个需要 bytes 类型的对象的函数/方法,因此会引发一个错误,清楚地说明:

TypeError: a bytes-like object is required, not 'str'

因此需要字符串的encode 方法,应用于str 值并返回bytes 值:

>>> s = "Hello world"
>>> print(type(s))
<class 'str'>
>>> byte_s = s.encode()
>>> print(type(byte_s))
<class 'bytes'>
>>> print(byte_s)
b"Hello world"

这里b'Hello world' 中的前缀b 表示这确实是一个字节对象。然后,您可以将它传递给任何期望它的函数,以使其顺利运行。

【讨论】:

【参考方案4】:

一点编码就可以解决这个问题:

客户端:

message = input("->")
clientSocket.sendto(message.encode('utf-8'), (address, port))

服务器端:

data = s.recv(1024)
modifiedMessage, serverAddress = clientSocket.recvfrom(message.decode('utf-8'))

【讨论】:

你的客户端不行:sendto需要3个参数,消息服务器地址和相关端口 消息、地址和端口。对我来说似乎是 3 个参数并且适用于我的! :)【参考方案5】:

只需将clientSocket.sendto(message,(serverName, serverPort)) 中传递的消息参数替换为clientSocket.sendto(message.encode(),(serverName, serverPort))。然后你就可以在python3

中成功运行了

【讨论】:

以上是关于TypeError:需要一个类似字节的对象,而不是“str”的主要内容,如果未能解决你的问题,请参考以下文章

“TypeError:在 OAuth 2.0 回调请求期间需要一个类似字节的对象,而不是 'str'”

诱变剂:TypeError:需要一个类似字节的对象,而不是“str”

TypeError:需要一个类似字节的对象,而不是“str”套接字编程

Django Rest Framework TypeError需要一个类似字节的对象,而不是'str'

TypeError:需要一个类似字节的对象,而不是使用 pickle 加载时的“str”

TypeError:在尝试发送 http 请求时需要一个类似字节的对象,而不是“str”