无需文件,实现序列化 / 反序列化 Python 对象

无需文件,实现序列化 / 反序列化 Python 对象

情景:

有一些特殊的情景,需要两台机器通过 ssh 传输一些数据。

当然,通过文件传输 (sftp) 是最为方便的了。

但是不想有 io 怎么办呢?

我们需要用到两个 python build-in 的包:

  • base64 : 听名字就知道是干嘛的
  • pickle : 序列化 / 反序列化 Python 的一些基础对象如 dict, list 等

直接上代码:

服务端 (Server)

~/trans.py

trans.py
1
2
3
4
5
6
7
import base64
import pickle

msg = ['message', 'date', 'author', 'hash']
base64.b64encode(pickle.dumps(msg))

print msg #直接打印到stdout里面去

客户端 (Client)

client.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import base64
import pickle
import subprocess


stdout, stderr = subprocess.Popen("ssh user@ip -c 'python trans.py'", shell=True, stdout = subprocess.PIPE)

ret = ""
while True:
line = sshout.readline()
if line != '':
ret += line.rstrip('\n')
else:
break
info = base64.b64decode(ret)
msg = pickle.loads(info)

另外,客户端代码里面的这种方式,是能够实时从 buffer 里面读的。也就是说,远程输出一点内容,本地就能读到一点内容。

为何要这样做呢?这不是画蛇添足么?

你可能会问,为何要用 base64 来编码呢?其实只是因为 pickle 直接 dump 出来的字符串,如果直接 print 到 stdout,格式会非常难看,个人觉得会很容易出问题。比如你可以试试这样:

1
>>> print pickle.dumps({"我的": "就是你的"})

其输出为:

1
2
3
4
5
6
(dp0
S'\xe6\x88\x91\xe7\x9a\x84'
p1
S'\xe5\xb0\xb1\xe6\x98\xaf\xe4\xbd\xa0\xe7\x9a\x84'
p2
s.

来试试

1
2
3
4
5
6
7
8
9
10
>>> s = """(dp0
S'\xe6\x88\x91\xe7\x9a\x84'
p1
S'\xe5\xb0\xb1\xe6\x98\xaf\xe4\xbd\xa0\xe7\x9a\x84'
p2
s.
"""

>>> pickle.loads(s)
{'\xe6\x88\x91\xe7\x9a\x84': '\xe5\xb0\xb1\xe6\x98\xaf\xe4\xbd\xa0\xe7\x9a\x84'}

当然,这里是可以被解析的,但是我并没有通过 ssh 来传输信息。

不同的 ssh wrap,可能对 stdout 的 buffer 处理不同。试想如果把这个信息 decode 或者 encode,或者替换掉非法字符,或者去掉换行符,那么我们就会很难受了。

如果用 base64 来编码一下呢?

1
2
>>> print(base64.b64encode(pickle.dumps({"我的": "就是你的"})))
KGRwMApTJ1x4ZTZceDg4XHg5MVx4ZTdceDlhXHg4NCcKcDEKUydceGU1XHhiMFx4YjFceGU2XHg5OFx4YWZceGU0XHhiZFx4YTBceGU3XHg5YVx4ODQnCnAyCnMu

多漂亮,不是吗?

无需文件,实现序列化 / 反序列化 Python 对象

https://robinxb.com/posts/2015/base64-with-ssh/

作者

薯条

发布于

2014-09-28

更新于

2024-01-15

许可协议

评论