Python I';我得到了TypeError:';str';不支持缓冲区接口

Python I';我得到了TypeError:';str';不支持缓冲区接口,python,sockets,python-3.x,Python,Sockets,Python 3.x,我正在尝试使用套接字连接到FTP服务器。我正在学习网络编程,所以我不会尝试使用ftplib。我搜索了stackoverflow的所有地方,因为有类似的问题,我尝试了解决方案堆栈用户必须提供的一切,但到目前为止没有一个有效。知道发生了什么事吗 def connect_to_target(username, password): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((target, 21))

我正在尝试使用套接字连接到FTP服务器。我正在学习网络编程,所以我不会尝试使用ftplib。我搜索了stackoverflow的所有地方,因为有类似的问题,我尝试了解决方案堆栈用户必须提供的一切,但到目前为止没有一个有效。知道发生了什么事吗

def connect_to_target(username, password):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((target, 21))
    data = s.recv(1024).decode()
    s.send('USER' + username + '\r\n').encode()
    data = s.recv(1024).decode()
    s.send('PASS' + password + '\r\n').encode()
    data = s.recv(3).decode()
    s.send('QUIT\r\n')
    s.close()
    return data
翻译说问题出在第13行

s.send('USER' + username + '\r\n').encode(). 
我尝试了一种不同的变体,如:

s.send('USER' + username + '\r\n'.encode())
当我尝试后者时,它给了我:

TypeError: Can't convert 'bytes' object to str implicitly
s.send()
需要一个编码的字节流作为参数。所以您需要类似于
s.send(str.encode())
的东西

当你这样做的时候

s.send('USER' + username + '\r\n').encode()
您没有对字符串进行编码,而是对
s.send()
的返回值进行编码。它读起来像
s.send(str).encode()
,这不是您想要的

您的第二次尝试更接近我们应该拥有的,但在本例中,您没有考虑运算符优先级

s.send('USER' + username + '\r\n'.encode())
这与首先执行
'\r\n'.encode()
,然后将字符串(
username
)与不允许的字节对象(
'\r\n'.encode()
)连接相同。此表达式的形式为
s.send(str2+str.encode())
,其中
运算符的优先级高于
+
运算符,就像在数学中加法之前先乘法一样

您希望对整个字符串进行编码。您这样做的方式只对字符串的
'\r\n'
部分进行编码

因此,您需要用括号将字符串连接起来,以便在编码之前首先执行连接。因此,您需要以下内容:

s.send(('USER' + username + '\r\n').encode())
#      ^                          ^ notice the parentheses here
这是我们之前期望的
s.send(str.encode())
形式。

s.send()
期望编码字节流作为参数。所以您需要类似于
s.send(str.encode())
的东西

当你这样做的时候

s.send('USER' + username + '\r\n').encode()
您没有对字符串进行编码,而是对
s.send()
的返回值进行编码。它读起来像
s.send(str).encode()
,这不是您想要的

您的第二次尝试更接近我们应该拥有的,但在本例中,您没有考虑运算符优先级

s.send('USER' + username + '\r\n'.encode())
这与首先执行
'\r\n'.encode()
,然后将字符串(
username
)与不允许的字节对象(
'\r\n'.encode()
)连接相同。此表达式的形式为
s.send(str2+str.encode())
,其中
运算符的优先级高于
+
运算符,就像在数学中加法之前先乘法一样

您希望对整个字符串进行编码。您这样做的方式只对字符串的
'\r\n'
部分进行编码

因此,您需要用括号将字符串连接起来,以便在编码之前首先执行连接。因此,您需要以下内容:

s.send(('USER' + username + '\r\n').encode())
#      ^                          ^ notice the parentheses here
这是我们之前期望的
s.send(str.encode())
格式。

用于此行

s.send('USER' + username + '\r\n').encode()
s.send('USER' + username + '\r\n'.encode())
您正在调用
encode
,就像它是从
s.send
返回任何内容的方法一样,这可能不是您想要的

这条线

s.send('USER' + username + '\r\n').encode()
s.send('USER' + username + '\r\n'.encode())
您只对序列中的最后一个字符串调用encode

'\r\n'.encode()
由于其中一个字符串已编码(到
bytes
type),而其他字符串仍然是正常的
str
类型,因此结果连接将无法工作

要使其工作,您需要创建一个整批的字符串,并对其进行编码

s.send('USER{}\r\n'.format(username).encode())
由于该行的
+
运算符,将在不创建任何临时字符串的情况下执行此操作。

s.send('USER' + username + '\r\n').encode()
s.send('USER' + username + '\r\n'.encode())
您正在调用
encode
,就像它是从
s.send
返回任何内容的方法一样,这可能不是您想要的

这条线

s.send('USER' + username + '\r\n').encode()
s.send('USER' + username + '\r\n'.encode())
您只对序列中的最后一个字符串调用encode

'\r\n'.encode()
由于其中一个字符串已编码(到
bytes
type),而其他字符串仍然是正常的
str
类型,因此结果连接将无法工作

要使其工作,您需要创建一个整批的字符串,并对其进行编码

s.send('USER{}\r\n'.format(username).encode())

由于
+
运算符的原因,将不会创建任何临时字符串。

可能
s.send('USER'+username+'\r\n').encode())
?或
s.send('USER{}\r\n'.format(username).encode())
@ace有效,谢谢!但是我很好奇,你知道为什么s.send('USER'+username+'\r\n').encode()代替s.send('USER'+username+'\r\n'.encode())?@ace等等,是不是。s.send中的encode('USER'+username+'\r\n'.encode())只编码最后一部分'\r\n',而不是整个字符串,这就是为什么括号版本有效?可能是
s.send('USER'+username+'\r\n').encode())
?或者
s.send('USER{}\r\n'.format(username).encode())
@ace有效,谢谢!但是我很好奇,你知道为什么s.send('USER'+username+'\r\n').encode()代替s.send('USER'+username+'\r\n'.encode())?@ace等等,是不是。s.send中的encode('USER'+username+'\r\n'.encode())只编码最后一部分'\r\n'而不是整个字符串,这就是为什么括号版本起作用的原因?