在Python版本之间在套接字上发送numpy数组,ascii错误

时间:2017-08-29 14:54:38

标签: python sockets pickle

我需要在同时运行的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。我不确定如何继续。有什么想法吗?

1 个答案:

答案 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.]]
相关问题