丢失了重要的.py文件(被覆盖为0字节文件),但旧版本仍然作为模块加载在ipython中——可以找回吗?

问题描述 投票:0回答:3

在管理多个不同的屏幕会话时,在其中许多会话中使用 vim 打开,在尝试“组织”我的会话的过程中,我设法用 0Byte 文件覆盖了一个非常重要的 .py 脚本。

但是,我打开了一个 ipython 实例,当将同一个 .py 文件作为模块运行时,它仍然记得曾经存在的代码!

所以我刚刚学到了关于备份的惨痛教训(我的最后一个备份是大约一周前由 vim 完成的,这会让我有很多工作要做),或者是否有任何可能的、可以想象的方法来检索 .py来自已加载模块的文件?我可能因为如此漫不经心而应得的,但我在这里真的很绝望。

python linux vim ipython recovery
3个回答
23
投票

如评论中所述,

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!'

但是,不 - 我不知道有任何更直接的方法来获取模块并获取源代码。


1
投票

当进程仍在运行时,您可以查看命名空间以查找要恢复的候选对象:

>>> 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
$

-1
投票

您应该能够使用

inspect

在 Ipython 会话中导入

inspect

,并且假设您正在尝试恢复 
myModule
,请执行以下操作:

q = inspect.getsource(myModule)



并将

q

 写入文件。

[编辑] 这对我使用 Python 2.7.6、IPython 1.2.1 模拟问题很有用

[编辑 #2]

© www.soinside.com 2019 - 2024. All rights reserved.