pickle.load - EOFError: Ran out of input
So, if the error you get is indeed "pickle: run out of input", that propably means you messed your directories in the code above, and are trying to read an empty file with the same name as your obj
file is.
Actually, as it is, this line in your code:
self.mainTerminal=pg.image.load(path.join(img_main_folder,self.main_uncode
("tr.obj"))).convert_alpha()
Is completly messed up. Just read it and you can see the problem: you are passing to the main_uncode
method just the file name, without directory information. And then, if it would by chance have worked, as I have poitned in the comments a while ago, you would try to use the unserialized image data as a filename from where to read your image. (You or someone else had probably thought that main_uncode
should write a temporary image file and writ the image data to that, so that Pygame could read it, but as it is, it is just returning the raw image data in a string).
Threfore, by fixing the above call and passing an actual path to main_uncode
, and further modifying it to write the temporary data to a file and return its path would fix the snippets of code above.
Second thing is I can't figure out why do you need this ".obj" file at all. If it is just for "security through obscurity" hopping people get your bundled file can't open the images, that is a thing far from a recommended practice. To sum up just one thing: it will delay legitimate uses of your file (like, you yourself does not seem to be able to use it ), while any attacker with sufficient motivation can still get to it easily. By opening an image, base-64 encoding and pickling it, and doing the reverse process you are doing essentially a no-operation. Even more, a pickle file can serialize and write to disk complex Python objects - but a base64 serialization of an image could be written directly to a file, with no need for pickle.
Third thing: just use with
to open all the files, not just the ones you read with the imaging library, Take your time to learn a little bit more about Python.
BlackFenix06
I am Italian, not English. I can not do complete sentences like these in English, so I use Google Translate to help me. But sometimes he writes crap. So I look crazy? I'm a person of simple tastes, I'm stupid, but I love computer language. I try to study it myself, I fall in love with Python. Too bad that it is user friendly and free, so unprotected.
Updated on July 09, 2022Comments
-
BlackFenix06 almost 2 years
I have an
.obj
file in which, previously, I transformed an image to base64 and saved withpickle
.The problem is when I try to load the
.obj
file withpickle
, convert the code into image from base64, and load it withpygame
.The function that loads the image:
def mainDisplay_load(self): main_folder = path.dirname(__file__) img_main_folder = path.join(main_folder, "sd_graphics") # loadImg self.mainTerminal = pg.image.load(path.join(img_main_folder, self.main_uncode("tr.obj"))).convert_alpha()
The function that decodes the file:
def main_uncode(self, object): openFile = open(object, "rb") str = pickle.load(openFile) openFile.close() fileData = base64.b64decode(str) return fileData
The error I get when the code is run:
str = pickle.load(openFile)
EOFError: Ran out of input
How can I fix it?
- Python version: 3.6.2
- Pygame version: 1.9.3
Update 1
This is the code I used to create the
.obj
file:import base64, pickle with open("terminal.png", "rb") as imageFile: str = base64.b64encode(imageFile.read()) print(str) file_pi = open("tr.obj","wb") pickle.dump(str,file_pi) file_pi.close() file_pi2 = open("tr.obj","rb") str2 = pickle.load(file_pi2) file_pi2.close() imgdata = base64.b64decode(str2) filename = 'some_image.jpg' # I assume you have a way of picking unique filenames with open(filename, 'wb') as f: f.write(imgdata)
Once the file is created, it is loaded and a second image is created. This is to check if the image is the same or there are errors in the conversion.
As you can see, I used part of the code to load the image, but instead of saving it, it is loaded into
pygame
. And that's where the mistake occurs.Update 2
I finally managed to solve it.
In the main code:
def mainDisplay_load(self): self.all_graphics = pg.sprite.Group() self.graphics_menu = pg.sprite.Group() # loadImg self.img_mainTerminal = mainGraphics(self, 0, 0, "sd_graphics/tr.obj")
In the library containing graphics classes:
import pygame as pg import base64 as bs import pickle as pk from io import BytesIO as by from lib.setting import * class mainGraphics(pg.sprite.Sprite): def __init__(self, game, x, y, object): self.groups = game.all_graphics, game.graphics_menu pg.sprite.Sprite.__init__(self, self.groups) self.game = game self.object = object self.outputGraphics = by() self.x = x self.y = y self.eventType() self.rect = self.image.get_rect() self.rect.x = self.x * tilesizeDefault self.rect.y = self.y * tilesizeDefault def eventType(self): openFile = open(self.object, "rb") str = pk.load(openFile) openFile.close() self.outputGraphics.write(bs.b64decode(str)) self.outputGraphics.seek(0) self.image = pg.image.load(self.outputGraphics).convert_alpha()
For the question of why I should do such a thing, it is simple:
any attacker with sufficient motivation can still get to it easily
Python is free and open.
On the one hand, we have a person who intentionally goes and modify and recover the hidden data. But if Python is an open language, as with even more complicated and protected languages, the most motivated are able to crack the game or program and retrieve the same data.
On the other hand, we have a person who knows only the basics, or not even that. A person who cannot access the files without knowing more about the language, or decoding the files.
So you can understand that decoding files, from my point of view, does not need to be protected from a motivated person. Because even with a more complex and protected language, that motivated person will be able to get what he wants. The protection is used against people who have no knowledge of the language.