Skip to main content
 首页 » 编程设计

python之我怎样才能找到为什么我的 pickle 数据如此之大

2025年05月04日12kevingrace

我有一个 python(如果重要的话是 3.1)应用程序,它可以挑选数据供另一个进程使用,并通过网络连接交换它们。出于某种原因,一些交换出乎意料地大......我可以理解一些 pickle 数据并弄清楚传输的是什么,但是仍然有一大块明显的二进制数据,我无法向自己解释,例如冗余字符串或大块二进制数据。

你知道是否有一个 wireshark 插件可以帮助我完成这项任务,或者你会推荐给那些试图弄清楚之前应该还有什么的人的另一个过程 =None对象通过连接传输?

RouteDirect 
q.).q.}q.(X...._RouteDirect__dst_nodeq.cnode 
Node 
q.).q.}q.(X...._Node__status_upq.NX...._Node__neighbourhoodq.NX...._Node__sendq.NX 
..._Node__cpeq 
cequation 
CPE 
q.).q.}q^M(X...._CPE__dim_countq.}q.X...._CPE__internal_nodesq.]q.ubX...._Node__major_stateq.NX...._Node__partition_idq.G?.$:..4.    X...._Node__name_idq.cnodeid 
NameID 
q.).q.}q.X^M..._NameID__nameq.X....checkq.sbX...._Node__dispatcherq.NX...._Node__pendingq.]q.cmessages 

^ 我能理解:RouteDirect、CPE 和 NameID 是我程序中的类。

v 我对此感到更惊讶:交换中不应该有那么多“纯二进制”数据,尽管 Iproto、Tflags、Isrc 和 Idst 是包含在这些数据中的字符串

 q0).q1}q2(X...._Range__maxq3X....1f40q4X...._Range__min_includedq5.X...._Range__max_includedq6.X...._ 
 Range__minq7h4ubX...._Component__dimensionq8h'ubh&).q9}q:h)X....Tflagsq;sbh+).q<}q=(h..h/h0).q>}q?             
 (h3X....02q@h5.h6.h7h@ubh8h9ubh&).qA}qBh)X....IprotoqCsbh+).qD}qE(h..h/h0).qF}qG(h3X... 
 
 .06qHh5.h6.h7hHubh8hAubh&).qI}qJh)X....IsrcqKsbh+).qL}qM(h..h/h0).qN}qO(h3X....7d59d8faqPh5.h6. 
 h7hPubh8hIubh&).qQ}qRh)X....IdstqS     
 sbh+).qT}qU(h..h/h0).qV}qW(h3X....00001011qXh5.h6.h7hXubh8hQubh&).qY}qZh)X....Tsrcq[sbh+).q\}q]          
 (h..h/h0).q^}q_(h3X....0bcfq`h5.h6.h7h`ubh8hYubusbX.... 

v 这真的令人费解。

qt).qu}qv(X...._LookupRequest__keyqwh!).qx}qyh$}qz(h&).q{}q|h)h*sbh+).q}}q~(h..h/h0).q.}q. 
(h3h4h5.h6.h7h4ubh8h{ubh&).q.}q.h)h;sbh+).q.}q.(h..h/h0).q.}q.(h3h@h5.h6.h7h@ubh8h.ubh&).q.}q.h)hCsbh+).q.}q.(h..h/h0).q.}q. 
(h3hHh5.h6.h7hHubh8h.ubh&).q.}q.h)hKsbh+).q.}q.(h..h/h0).q.}q.(h3hPh5.h6.h7hPubh8h.ubh&).q.}q.h)hSsbh+).q.}q.(h..h/h0).q.}q. 
(h3hXh5.h6.h7hXubh8h.ubh&).q.}q.h)h[sbh+).q.}q.(h..h/h0).q.}q. 
(h3h`h5.h6.h7h`ubh8h.ubusbX...._LookupRequest__nonceq.G?...u...X...._LookupRequest__fromq.h.).q.}q.(h.Nh.Nh.Nh 
h.).q.}q.(h.}q. 

最让我困惑的是,它似乎太有规律了,不像是 e.g.仅仅是二进制的 float /整数。它对数字和 [shub] 以及许多“孤立的”q 有一些亲和性……这让我想起了机器代码。还是只是我的眼睛?

Node 类中 pickle 支持的示例, # # 定义特殊的 pickle 行为。

def __getstate__(self): 
    """Indicate witch fields should be pickled.""" 
    state = copy.copy(self.__dict__) 
 
    # 'state' is a shallow copy: don't modify objects' content 
    # Make transients fields point to nothing 
    state['_Node__dispatcher'] = None 
    state['_Node__send'] = None 
    state['_Node__neighbourhood'] = None 
    state['_Node__status_up'] = None 
    state['_Node__data_store'] = None 
    state['_Node__running_op'] = None 
    state['_Node__major_state'] = None 
 
    return state 

许多其他对象(例如 CPE、RouteDirect)没有 __getstate__ 方法。当然,如果有某种技术不需要我遍历所有类的所有构造函数,我会很高兴。

请您参考如下方法:

啊,阅读/usr/lib/python3.1/pickle.py 代码至少让一点不那么晦涩:pickling 的输出确实是某些解释器的一些字节码,带有 push/pop 对来解释所见的常规模式。

BINPUT         = b'q'   # store stack top in memo; index is 1-byte arg 
BINGET         = b'h'   # push item from memo on stack; index is 1-byte arg 
EMPTY_TUPLE    = b')'   # push empty tuple 
MARK           = b'('   # push special markobject on stack 

等等

根据@Alfe 的评论,我使用 wireshark“跟随 TCP 流”和“另存为...”功能捕获原始流量,然后使用

x=pickle.load(open("wirecapture.bin","rb")) 

并使用 Python 评估器来更好地了解其中的内容。特别是使用

len(pickle.dump(x.my_field)) 

对于 dir(x) 报告的所有字段,我可以查明超大字段。不幸的是,我无法得到

for y in dir(x): 
   print("%s: %iKb"%(y,len(pickle.dumps(x[y])/1024)) 

正常工作(当 y == 'my_field' 时,x[y] 不是提取 x.my_field 的有效方法 > _< )