在管理多个不同的屏幕会话时,在其中许多会话中使用 vim 打开,在尝试“组织”我的会话的过程中,我设法用 0Byte 文件覆盖了一个非常重要的 .py 脚本。
但是,我打开了一个 ipython 实例,当将同一个 .py 文件作为模块运行时,它仍然记得曾经存在的代码!
所以我刚刚学到了关于备份的惨痛教训(我的最后一个备份是大约一周前由 vim 完成的,这会让我有很多工作要做),或者是否有任何可能的、可以想象的方法来检索 .py来自已加载模块的文件?我可能因为如此漫不经心而应得的,但我在这里真的很绝望。
如评论中所述,
inspect.getsource
将不起作用,因为它取决于原始文件(即module.__file__
)。
最佳选择:检查是否有
.pyc
文件(例如,foo.pyc
应该位于 foo.py
旁边)。如果有,可以使用Decompile Python 2.7 .pyc来反编译。
inspect
模块还缓存源。您可能会幸运地使用 inspect.getsource(module)
,或者 inspect.getsourcelines(module.function)
(如果过去曾被调用过)。
否则,您需要通过检查导出来“手动”重建模块(即
module.__globals__
)。常量和其他内容是显而易见的,对于函数,您可以使用 func.func_name
获取其名称,func.__doc__
获取文档字符串,inspect.getargspec(func)
获取参数,以及 func.func_code
获取有关代码的详细信息: co_firstlineno
将获取行号,然后 co_code
将获取代码。这里有更多关于反编译的内容:Exploring and decompiling python bytecode
例如,要使用
uncompyle2
:
>>> def foo():
... print "Hello, world!"
...
>>> from StringIO import StringIO
>>> import uncompyle2
>>> out = StringIO()
>>> uncompyle2.uncompyle("2.7", foo.func_code, out=out)
>>> print out.getvalue()
print 'Hello, world!'
但是,不 - 我不知道有任何更直接的方法来获取模块并获取源代码。
当进程仍在运行时,您可以查看命名空间以查找要恢复的候选对象:
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'readline', 'rlcompleter', 'test']
让我们看看我们准备了什么
test
:
>>> help(test)
Help on module test:
NAME
test
FILE
/Users/tfisher/code/ffi4wd/test.py
FUNCTIONS
call_cat(cat)
DATA
cat_name = 'commander sprinkles'
这比查看
test
内的当地人的输出更干净:
>>> dir(test)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'call_cat', 'cat_name', 'json']
使用inspect模块,我们可以获得函数的参数规范:
>>> inspect.getargspec(test.call_cat)
ArgSpec(args=['cat'], varargs=None, keywords=None, defaults=None)
或者我们函数中的代码行:
>>> inspect.getsourcelines(test.call_cat)
(['def call_cat(cat):\n', ' print("Hello %s" % cat)\n'], 5)
与原版相当接近:
import json
cat_name = 'commander sprinkles'
def call_cat(cat):
print("Hello %s" % cat)
如果文件在导入后被删除并且尚未被较新的同名文件替换(
getsourcelines
如果可能的话使用对象缓存),这应该有效:
$ python -V
Python 2.7.10
$ ls | grep test
$