Python如何从内存中找回源代码

首先,项目必须在运行,代码必须驻留在内存中

 

安装GDB(pyrasite需要)

apt-get update && apt-get install gdb

安装pyrasite,它让你能够跟正在运行的进程通信

pip install pyrasite

安装uncomplyle6,它能让你获取内存中存在的对象的源代码

pip install uncompyle6

找到正在运行的进程的PID

ps aux | grep python

使用pyrasite附着一个交互提示符

pyrasite-shell <PID>

现在你在交互终端中了,导入你要恢复的代码

>>> from my_package import my_module

找出你需要恢复的函数和类

>>> dir(my_module)
['MyClass', 'my_function']

把函数源代码提取出来

>>> import uncompyle6
>>> import sys
>>> uncompyle6.main.uncompyle(
    2.7, my_module.my_function.func_code, sys.stdout
)
# uncompyle6 version 2.9.10
# Python bytecode 2.7
# Decompiled from: Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
# [GCC 5.4.0 20160609]
# Embedded file name: /srv/my_package/my_module.py
function_body = "appears here"

对于类,你需要逐个提取每一个方法的文档

>>> uncompyle6.main.uncompyle(
    2.7, my_module.MyClass.my_method.im_func.func_code, sys.stdout
)
# uncompyle6 version 2.9.10
# Python bytecode 2.7
# Decompiled from: Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
# [GCC 5.4.0 20160609]
# Embedded file name: /srv/my_package/my_module.py
class_method_body = "appears here"

举例说明:

假如现在已经用如下命令进入到了交互模式(注意:你要首先cd到你项目所在的目录)

 

pyrasite-shell <PID>

我的代码有一个xmlparser模块,这个模块代码里面有个XmParser类,我现在想恢复这个类里面的方法

 

 

 

>>> import xmlparser
>>> dir(xmlparser.XmlParser)

打印的结果为:

 

 

['__abstractmethods__', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__metaclass__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_abc_cache', '_abc_negative_cache', '_abc_negative_cache_version', '_abc_registry', 'getContentAppendStr', 'getSummarPicStr', 'handleContent', 'handleSpecialModuleActor', 'handleSpecialModuleConcert', 'handleSpecialModuleMovieAndTv', 'handleSpecialModuleMusic', 'handleSpecialModulePlot', 'handleSpecialModuleRole', 'handleSpecialModuleStaff', 'handleSpecialModuleVariety', 'handleSpecialModules', 'obtainAbstract', 'obtainAmbiTitle', 'obtainBaseinfo', 'obtainContent', 'obtainKeywords', 'obtainLemmaStatistic', 'obtainPolysemantList', 'obtainReference', 'obtainTags', 'obtainTitle', 'removeTagWithOutSup', 'retainSupAndBr']

可以看到,这是这个类里面的所有方法,接下来就可以反编译得到指定方法的代码了,比如我想得到obtainAmbiTitle的代码

 

 

uncompyle6.main.decompile(2.7, xmlparser.XmlParser.obtainAmbi.func_code, sys.stdout)

上述命令的执行结果为:

 

 

# uncompyle6 version 2.15.0
# Python bytecode 2.7
# Decompiled from: Python 2.7.5 (default, Nov  6 2016, 00:28:07) 
# [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
# Embedded file name: /search/data2/dlj/work/baiduHtmlExtract-dev/xmlparser.py
ul = doc.select('ul.polysemantList-wrapper.cmn-clearfix')
if ul:
    sele = ul[0].select('span.selected')
    if sele:
        return RuleUtils.standardHtmlEscape(sele[0].text.strip())<uncompyle6.semantics.pysource.SourceWalker object at 0x1f2d790>ul = doc.select('ul.polysemantList-wrapper.cmn-clearfix')
if ul:
    sele = ul[0].select('span.selected')
    if sele:
        return RuleUtils.standardHtmlEscape(sele[0].text.strip())<uncompyle6.semantics.pysource.SourceWalker object at 0x1f2d790>

如上黑体部分就是代码了

 

有的时候我们想得到的不是类的方法,而是某个变量,那么可以直接跟pdb的时候一样,比如我想知道xmlparser模块中的变量escapeRex的值,可以如下:

 

>>>import xmlparser
>>>print xmlparser.excapeRex

其实就跟我们在pdb中调试的时候获取变量的值有点类似
 

 


 

 


 

 


 

 


 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值