12.10.4 二进制数据
所有传递到服务器的值都会被编码,并自动转义。不过,有些数据类型包含的字符可能不是合法的XML。例如,二进制图像数据可能包括ASCII控制范围0到31中的字节值。要传递二进制数据,最好使用Binary类对其编码来传输。
import xmlrpc.client
import xml.parsers.expat
server = xmlrpc.client.ServerProxy('http://localhost:9000')
s = b'This is a string with control characters\x00'
print('Local string:',s)
data = xmlrpc.client.Binary(s)
response = server.send_back_binary(data)
print('As binary:',response.data)
try:
print('As string:',server.show_type(s))
except xml.parsers.expat.ExpatError as err:
print('\nERROR:',err)
如果将一个包含NULL字节的串传递到show_type(),那么XML解析器处理响应时会产生一个异常。
运行结果:
还可以利用pickle使用Binary对象发送对象。通过网络向可执行代码发送大量数据时,通常存在一些安全问题,这里也不例外(也就是说,除非通信通道是安全的,否则不要这么做)。
import xmlrpc.client
import pickle
import pprint
class MyObj:
def __init__(self,a,b):
self.a = a
self.b = b
def __repr__(self):
return 'MyObj({!r},{!r})'.format(self.a,self.b)
server = xmlrpc.client.ServerProxy('http://localhost:9000')
o = MyObj(1,'b goes here')
print('Local:',id(o))
print(o)
print('\nAs object:')
pprint.pprint(server.show_type(o))
p = pickle.dumps(o)
b = xmlrpc.client.Binary(p)
r = server.send_back_binary(b)
o2 = pickle.loads(r.data)
print('\nFrom pickle:',id(o2))
pprint.pprint(o2)
Binary实例的数据属性包含对象的腌制版本,所以在使用之前必须解除腌制。这一步得到一个不同的对象(有一个新的ID值)。
运行结果: