我需要在同时运行的Python2和Python3程序之间发送numpy数组。在做了一些研究之后,我决定通过套接字连接发送泡菜。
我能够建立连接并来回发送字符串,但尝试发送numpy数组会导致ascii错误。这是我的客户端/服务器正在做的事情:
### Imports on both client and server ###
import socket as sc
import numpy
try:
import cPickle as pickle
except ImportError:
import pickle
pickle.HIGHEST_PROTOCOL = 2
### Python2 client ###
data= numpy.ones((1, 60))
sock.connect(SERVER_ADDR)
try:
serialized_data = pickle.dumps(data, protocol=2)
except pickle.PicklingError as e:
raise e
try:
sock.send(serialized_data )
except sc.error as e:
logging.error('Connection ended')
### Python3 server ###
"""
Given a client socket, and until the client has closed the session:
- receive input from client
- unpickle and print it
"""
while client != '':
try:
data = client.recv(4096)
except sc.error as e:
if e.errno != errno.ECONNRESET:
print('Connection ended')
else:
try:
unserialized_input = pickle.loads(input) ##### ERROR HERE #####
except pickle.UnpicklingError as e:
raise e
else:
print(unserialized_input)
### Error on server ###
UnicodeDecodeError: 'ascii' codec can't decode byte 0xf0 in position 6: ordinal not in range(128)
我正在尝试搜索相关问题,但找不到任何相关的问题,除了建议here的解决方案,这对我不起作用,因为我需要使用Python2。我不确定如何继续。有什么想法吗?
答案 0 :(得分:2)
我在Python 3上重现了运行服务器的错误,在Python 2上运行了客户端。以下代码是一个可以在任何Pythons组合上运行服务器和客户端的示例。 Python 3上的pickle.loads
默认使用ascii
解码字符串。要将它们保留为发送的原始字节,请添加encoding='bytes'
作为参数。
我的协议是“从客户端读取所有内容,直到客户端关闭连接,然后反序列化”。如果要保持连接打开并发送多个序列化blob,则必须定义一个指示序列化blob长度的协议。
客户端:
import socket
import numpy
try:
import cPickle as pickle
except ImportError:
import pickle
sock = socket.socket()
data= numpy.ones((1, 60))
sock.connect(('localhost',8000))
serialized_data = pickle.dumps(data, protocol=2)
sock.sendall(serialized_data)
sock.close()
sock = socket.socket()
data= numpy.zeros((1, 60))
sock.connect(('localhost',8000))
serialized_data = pickle.dumps(data, protocol=2)
sock.sendall(serialized_data)
sock.close()
服务器:
from __future__ import print_function
import sys
import socket
import numpy
try:
import cPickle as pickle
except ImportError:
import pickle
s = socket.socket()
s.bind((b'',8000))
s.listen(1)
while True:
c,a = s.accept()
data = b''
while True:
block = c.recv(4096)
if not block: break
data += block
c.close()
if sys.version_info.major < 3:
unserialized_input = pickle.loads(data)
else:
unserialized_input = pickle.loads(data,encoding='bytes')
print(unserialized_input)
输出:
[[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1.]]
[[ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0.]]