Python 3.7: 通过 python 套接字发送文件时出错

Python 3.7: Error while sending a file through python socket

使用Python,我想发布数据到socket。
我在 Python 3.7 中编写了一个 client/server 程序来通过网络发送一个大的 csv 文件。客户端和服务器代码如下。

示例文件:

$ cat datafile.csv
id,first_name,gender,car,money,city,country,jobtitle
1,Marline,Female,Ford,.94,Kanzaki,Japan,Food Chemist
2,Ker,Male,Lincoln,.46,Fort Beaufort,South Africa,Marketing Manager
3,Wallie,Male,Land Rover,.12,Eystur,Faroe Islands,Senior Quality Engineer
4,Deonne,Female,Ford,.72,Fontaínhas,Portugal,Social Worker
5,Barnaby,Male,Volkswagen,[=12=].60,Taoyuan,China,Web Developer I
6,Maximilian,Male,GMC,.19,Nowy Dwór Gdański,Poland,Engineer IV
7,Wake,Male,Buick,.08,Kazuno,Japan,Food Chemist
8,Truman,Male,Infiniti,.60,Içara,Brazil,Senior Quality Engineer
9,Mufi,Female,Ford,.55,Gununglajang,Indonesia,Actuary
10,Dniren,Female,Ford,.71,Yuyapichis,Peru,Software Consultant

客户端服务器程序如下:

客户代码:

$ cat client.py

import socket

HOST = 'server ip'        # The remote host
PORT = 42050              # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
f = open('/home/vijee/data/datafile.csv', 'rb')
print "Sending Data ...."  
l = f.read()
while True:      
    for line in l:
        s.send(line)    
    break
f.close()
print "Sending Complete"
s.close()

服务器代码:

$ cat server.py

import socket

HOST = 'local ip'         # server ip
PORT = 42050              # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
print "Server running", HOST, PORT
s.listen(5)
conn, addr = s.accept()
print'Connected by', addr

while True:
    data = "".join(iter(lambda:conn.recv(1),"\n"))       
    print data   
    if not data: break                

print "Done Receiving"
conn.close()

在执行 client.py 脚本时出现以下错误:

bash_shell:~$ python /home/vijee/data/python_code/server.py 
Server running localhost 9000
Connected by ('127.0.0.1', 42950)

bash_shell:~$ python /home/vijee/data/python_code/client.py 
Sending Data ....
Traceback (most recent call last):
  File "/home/vijee/data/python_code/client.py", line 12, in <module>
    s.send(line)    
TypeError: a bytes-like object is required, not 'int'

我知道这是个小错误。但是找不到错误。

l 是一个 bytes 对象。来自 documentation:

While bytes literals and representations are based on ASCII text, bytes objects actually behave like immutable sequences of integer

所以当你写 for line in l: 时,line 的每个值都是一个包含文件中单个字节的整数。 s.send() 的参数必须是 bytes,而不是整数。所以你可以使用:

s.send(bytes([line]))

将整数转换为 bytes 对象。不要忘记 [] —— bytes 构造函数需要一个序列。如果你只写bytes(line),它会创建一个bytes长度为line的对象,内容都是零字节。

循环尝试一次发送一个字节并没有任何原因。只需使用

s.send(l)

一次发送。

顺便说一句,变量名 line 表明您认为您是逐行发送,而不是逐字节发送。那没有发生。由于您以二进制模式打开文件,因此它没有行的概念。即使您以文本模式打开它,l 也将是一个字符串,而不是一系列行;如果你想要一系列的行,你应该使用 f.readlines()for line in f:.

在 Python 3.9:

下测试

替换为:

s.send(line) 

有了这个:

s.send(bytes(line, encoding="utf-8"))