丢失了重要的.py文件(覆盖为0byte文件),但旧版本仍作为模块加载在IPYTHON中--可以检索吗?
在管理几个不同的屏幕会话时,vim在其中许多会话中打开,在尝试“组织”会话的过程中,我设法用一个0字节的文件覆盖了一个非常重要的.py脚本 但是,我打开了一个ipython实例,当作为模块运行同一个.py文件时,它仍然记得以前的代码丢失了重要的.py文件(覆盖为0byte文件),但旧版本仍作为模块加载在IPYTHON中--可以检索吗?,python,linux,vim,ipython,recovery,Python,Linux,Vim,Ipython,Recovery,在管理几个不同的屏幕会话时,vim在其中许多会话中打开,在尝试“组织”会话的过程中,我设法用一个0字节的文件覆盖了一个非常重要的.py脚本 但是,我打开了一个ipython实例,当作为模块运行同一个.py文件时,它仍然记得以前的代码 那么,我是否刚刚学到了一堂关于备份的艰苦的教训(我的上一次备份是大约一周前由vim完成的,这会让我有很多工作要做),或者是否有任何可能的、可以想象的方法从已加载的模块中检索.py文件?我可能应该为自己如此傲慢而受到惩罚,但我在这里非常绝望。你应该能够使用检查 在Ip
那么,我是否刚刚学到了一堂关于备份的艰苦的教训(我的上一次备份是大约一周前由vim完成的,这会让我有很多工作要做),或者是否有任何可能的、可以想象的方法从已加载的模块中检索.py文件?我可能应该为自己如此傲慢而受到惩罚,但我在这里非常绝望。你应该能够使用
检查
在Ipython会话中导入inspect
,并假设您正在尝试恢复myModule
,请执行以下操作:
q=inspect.getsource(myModule)
并将q
写入文件
[编辑]
这对我使用Python2.7.6和iPython1.2.1模拟问题很有效
[编辑#2]
如注释中所述,inspect.getsource
将不起作用,因为它依赖于原始文件(即,模块。\uuuuuuuuu文件
)
最佳选择:检查是否有.pyc
文件(例如,foo.pyc
应该在foo.py
旁边)。如果有,您可以使用来反编译它
inspect
模块还缓存源代码。您可能会幸运地使用inspect.getsource(module)
,或者inspect.getsourcelines(module.function)
(如果以前调用过)
否则,您需要通过检查导出来“手动”重建模块(即,module.\uuuu globals\uuu
)。常量和其他东西是显而易见的,对于函数,您可以使用func.func\u name
获取其名称,func.\uu doc\uu
获取文档字符串,inspect.getargspec(func)
获取参数,func.func\u code
获取有关代码的详细信息:co\u firstlineno
将获取行号,然后,co\u code
将获得代码。这里有更多关于反编译的内容:
例如,要使用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']
让我们看看我们为测试准备了什么:
>>> help(test)
Help on module test:
NAME
test
FILE
/Users/tfisher/code/ffi4wd/test.py
FUNCTIONS
call_cat(cat)
DATA
cat_name = 'commander sprinkles'
它的输出比查看测试中的局部变量更干净:
>>> dir(test)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'call_cat', 'cat_name', 'json']
使用,我们可以获得函数的参数规范:
>>> 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
使用对象缓存),则该选项应该有效:
要检索在控制台中键入的内容:import readline;打印“\n”。为范围内的i(readline.get\u history\u item(i))加入([str(readline.get\u current\u history\u length())])
,但这可能无法解决您的问题。我认为这不是他真正想要的。他知道他加载的模块的名称,他希望检索当前加载模块的内容?(我认为ipython生成pyc文件,但不确定)Slater是对的。我担心的是ipython记住的可执行脚本是什么样子的,以及它的格式是否可以重新构造为简单的.py。我知道,当我在重新加载模块之前更改.py文件的内容时,ipython会抛出更改前脚本中的错误,同时显示更改后脚本的实际内容。这让我相信,这不仅仅是在后台保存文件的可读格式。这非常重要,但还不足以使用源代码管理或备份?如果文件已被删除(刚刚测试过),这将不起作用。我已使用2和3对此进行了测试,但无法使其正常工作,因此我担心我的否决票将保留。删除源文件和截断源文件之间可能存在差异。此外,inspect
会缓存源文件。从新会话中重试(即,导入模块,删除/截断文件,然后尝试获取源)。@DavidWolever我认为这个缓存点使我认为我的测试版本起作用;请参见编辑2的第9行。很抱歉,您遗漏了最后两个步骤:开始使用源代码管理,永远不要再犯这个错误!pfft,但如果有人去做这样愚蠢的事情,我怎么能得到这些甜蜜的互联网积分呢?说得清楚,你的链接不只是用来反编译.pyc文件的吗?或者uncompyle2能够解释module.function.func_code.co_代码,或者dis.dis(module.function)?@LukeDavis uncompyle可以处理func_代码
。请参阅编辑。检查。getsourcelines
将不起作用;请参阅对Ryan答案的评论。@DavidWolever您确定吗getsourcelines
正在我的计算机上运行,但文件丢失。它的机制可能不同于getsource
。另外,inspect
会缓存源代码。从新会话中重试(即,导入模块,删除/截断文件,然后尝试获取源代码)。我看到您的编辑重新:getsourcelines
。我将保留我的答案,因为它可能适用于OP——交换文件的内容意味着重新触发导入,因为文件较新;情况未必如此。编辑:当我点击回车键时,你的评论进来了:是的——我在2.7.10的源代码中看到了缓存。
$ python -V
Python 2.7.10
$ ls | grep test
$