如果删除了原始的Python文件,那么是否真的不可能取消python类?
假设您有以下内容:
file ='hey.py'
class hey:
def __init__(self):
self.you =1
ins = hey()
temp = open("cool_class", "wb")
pickle.dump(ins, temp)
temp.close()
现在假设您删除文件hey.py,然后运行以下代码:
pkl_file = open("cool_class", 'rb')
obj = pickle.load(pkl_file)
pkl_file.close()
您会遇到错误。我知道,如果您没有文件hey.py的班级和该课程的属性,则可能无法解决问题。泡菜。但是,必须找出序列化类的属性是什么,然后我可以重建已删除的文件并打开类。我有2岁的泡菜,并且删除了用来构建它们的文件,我只需要找出这些类的属性是什么,以便我可以重新打开这些泡菜
##### update
我知道从最初包含旧类的模块的错误消息中,让我们称其为“ hey.py”。我知道班级的名字让我们称其为“你”。但是,即使在重新创建模块并建立了一个名为“您”的课程之后,我仍然无法让泡菜打开。因此,我在hey.py
模块上写下了此代码:
class hey:
def __init__(self):
self.hey = 1
def __setstate__(self):
self.__dict__ = ''
self.you = 1
但是我收到错误消息:typeError: init ()采用1个位置参数,但给出了2个
## ####### update 2:
我更改了代码,
class hey:
然后
class hey():
我得到了一个属性,但它并没有告诉我缺少什么属性。然后,我在此行上执行
obj= pickletools.dis(file)
并在Pickletools.py文件上遇到了一个错误
def _genops(data, yield_end_pos=False):
if isinstance(data, bytes_types):
data = io.BytesIO(data)
if hasattr(data, "tell"):
getpos = data.tell
else:
getpos = lambda: None
while True:
pos = getpos()
code = data.read(1)
opcode = code2op.get(code.decode("latin-1"))
if opcode is None:
if code == b"":
raise ValueError("pickle exhausted before seeing STOP")
else:
raise ValueError("at position %s, opcode %r unknown" % (
"<unknown>" if pos is None else pos,
code))
if opcode.arg is None:
arg = None
else:
arg = opcode.arg.reader(data)
if yield_end_pos:
yield opcode, arg, pos, getpos()
else:
yield opcode, arg, pos
if code == b'.':
assert opcode.name == 'STOP'
break
:
code = data.read(1)
say:attributeError:'str'对象没有属性'read'
我现在将尝试Pickletools
# 中的其他方法#########
这是保存的类:
因此,这是所讨论的类:
class fss(frozenset):
def __init__(self, *args, **kwargs):
super(frozenset, self).__init__()
def __str__(self):
str1 = lbr + "{}" + rbr
return str1.format(','.join(str(x) for x in self))
现在请记住,腌制的对象主要是字典,该类别存在于字典中。执行后,
obj= pickletools.genops(file)
我将获得以下输出:
我看不出我将如何构造使用该数据的类别的类不知道课是什么。
##############
我能够看到您的代码的工作原理,但是我从2年前保存的腌制文件,并且其模块和类已删除很久以来,我就无法将其打开为一个字节般的对象,对我来说似乎是必要的。
因此,文件的路径是
file ='hey.pkl'
pkl_file = open(file, 'rb')
x = MagicUnpickler(io.BytesIO(pkl_file)).load()
返回错误:
TypeError: a bytes-like object is required, not '_io.BufferedReader'
但是我认为该对象是一个字节对象,因为我使用open(file,'rb')
########## ###更新#5
实际上,我认为在AKX的帮助下,我解决了问题。
因此,使用代码:
pkl_file = open(name, 'rb')
x = MagicUnpickler(pkl_file).load()
然后,我创建了两个空白模块,这些模块曾经包含在保存泡菜中找到的类,但是我不必将这些类放在上面。我在文件pickle.py.py
中遇到错误:
def load_reduce(self):
stack = self.stack
args = stack.pop()
func = stack[-1]
try:
stack[-1] = func(*args)
except TypeError:
pass
dispatch[REDUCE[0]] = load_reduce
因此,除了错误之后,一切都起作用。我真的要感谢AKX帮助我。实际上,我已经尝试解决这个问题已有5年了,因为我使用泡菜的频率要比大多数程序员多得多。我曾经不明白,如果您更改课程,那么这会破坏与该类别保存的任何腌制文件,因此我一次又一次地遇到了这个问题。但是,现在我要回顾一些已有2年的代码,并且看起来有些文件已被删除,将来我将非常需要此代码。因此,我非常感谢您为解决这个问题解决的帮助。
Suppose you have the following:
file = 'hey.py'
class hey:
def __init__(self):
self.you =1
ins = hey()
temp = open("cool_class", "wb")
pickle.dump(ins, temp)
temp.close()
Now suppose you delete the file hey.py and you run the following code:
pkl_file = open("cool_class", 'rb')
obj = pickle.load(pkl_file)
pkl_file.close()
You'll get an error. I get that it's probably the case that you can't work around the problem of if you don't have the file hey.py with the class and the attributes of that class in the top level then you can't open the class with pickle. But it has to be the case that I can find out what the attributes of the serialized class are and then I can reconstruct the deleted file and open the class. I have pickles that are 2 years old and I have deleted the file that I used to construct them and I just have to find out what what the attributes of those classes are so that I can reopen these pickles
#####UPDATE
I know from the error messages that the module that originally contained the old class, let's just call it 'hey.py'. And I know the name of the class let's call it 'you'. But even after recreating the module and building a class called 'you' I still can't get the pickle to open. So I wrote this code on the hey.py
module like so:
class hey:
def __init__(self):
self.hey = 1
def __setstate__(self):
self.__dict__ = ''
self.you = 1
But I get the error message: TypeError: init() takes 1 positional argument but 2 were given
#########UPDATE 2:
I Changed the code from
class hey:
to
class hey():
I then got an AttributeError but it doesn't tell me what attribute is missing. I then performed
obj= pickletools.dis(file)
And got an error on the pickletools.py file here
def _genops(data, yield_end_pos=False):
if isinstance(data, bytes_types):
data = io.BytesIO(data)
if hasattr(data, "tell"):
getpos = data.tell
else:
getpos = lambda: None
while True:
pos = getpos()
code = data.read(1)
opcode = code2op.get(code.decode("latin-1"))
if opcode is None:
if code == b"":
raise ValueError("pickle exhausted before seeing STOP")
else:
raise ValueError("at position %s, opcode %r unknown" % (
"<unknown>" if pos is None else pos,
code))
if opcode.arg is None:
arg = None
else:
arg = opcode.arg.reader(data)
if yield_end_pos:
yield opcode, arg, pos, getpos()
else:
yield opcode, arg, pos
if code == b'.':
assert opcode.name == 'STOP'
break
At this line:
code = data.read(1)
saying: AttributeError: 'str' object has no attribute 'read'
I will now try the other methods in the pickletools
########### UPDATE 3
I wanted to see what happened when I saved an object composed mostly of dictionary but some of the values in the dictionaries were classes. This is the class that was saved:
so here is the class in question:
class fss(frozenset):
def __init__(self, *args, **kwargs):
super(frozenset, self).__init__()
def __str__(self):
str1 = lbr + "{}" + rbr
return str1.format(','.join(str(x) for x in self))
Now keep in mind that the object pickled is mostly a dictionary and that class exists within the dictionary. After performing
obj= pickletools.genops(file)
I get the following output:
I don't see how I would be able to construct the class referred to with that data if I hadn't known what the class was.
############### UPDATE #4
@AKK
Thanks for helping me out. I am able to see how your code works but my pickled file saved from 2 years ago and whose module and class have long since been deleted, I cannot open it into a bytes-like object which to me seems to be a necessity.
So the path of the file is
file ='hey.pkl'
pkl_file = open(file, 'rb')
x = MagicUnpickler(io.BytesIO(pkl_file)).load()
This returns the error:
TypeError: a bytes-like object is required, not '_io.BufferedReader'
But I thought the object was a bytes object since I opened it with open(file, 'rb')
############ UPDATE #5
Actually, I think with AKX's help I've solved the problem.
So using the code:
pkl_file = open(name, 'rb')
x = MagicUnpickler(pkl_file).load()
I then created two blank modules which once contained the classes found in the save pickle, but I did not have to put the classes on them. I was getting an error in the file pickle.py
here:
def load_reduce(self):
stack = self.stack
args = stack.pop()
func = stack[-1]
try:
stack[-1] = func(*args)
except TypeError:
pass
dispatch[REDUCE[0]] = load_reduce
So after excepting that error, everything worked. I really want to thank AKX for helping me out. I have actually been trying to solve this problem for about 5 years because I use pickles far more often than most programmers. I used to not understand that if you alter a class then that ruins any pickled files saved with that class so I ran into this problem again and again. But now that I'm going back over some code which is 2 years old and it looks like some of the files were deleted, I'm going to need this code a lot in the future. So I really appreciate your help in getting this problem solved.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,有了一些黑客和魔术,当然,您可以补充缺少的课程,但是我不能保证这对您可能遇到的所有泡菜数据都有效;首先,这不会触及
__ setstate __
/__降低__
协议,所以我不知道它们是否有效。给定一个脚本文件(
so72863050.py
在我的情况下):我们现在成功创建了一些我们无法加载的泡菜数据,因为我们忘记了这两个类。现在,由于 unflowlow noreferrer“面对某些失败(或至少一个属性)的魔术毫无疑问,综合了一个简单的班级AIR:
现在,当我们从上述
pickle_bytes
plin ol'pickle.loads()
无法加载...打印出来
时, 魔法!
Well, with a bit of hacking and magic, sure, you can hydrate missing classes, but I'm not guaranteeing this will work for all pickle data you may encounter; for one, this doesn't touch the
__setstate__
/__reduce__
protocols, so I don't know if they work.Given a script file (
so72863050.py
in my case):we now have successfully created some pickle data that we can't load anymore, since we forgot about those two classes. Now, since the unpickling mechanism is customizable, we can derive a magic unpickler, that in the face of certain defeat (or at least an AttributeError), synthesizes a simple class from thin air:
Now, when we run that magic unpickler against a stream from the aforebuilt
pickle_bytes
that plain ol'pickle.loads()
couldn't load...prints out
Hey, magic!
函数load_reduce(self)中的错误可以通过以下方式重新创建:
AKX的答案在类从基本类别的基础类,dict,list,...
The error in function load_reduce(self) can be re-created by:
AKX's answer do not solve cases when the class inherit from base classes as set, dict, list,...