web-dev-qa-db-fra.com

pickle.load - EOFError: Ran out of input

J'ai un .obj fichier dans lequel, auparavant, j'ai transformé une image en base64 et enregistré avec pickle.

Le problème est lorsque j'essaie de charger le .obj fichier avec pickle, convertissez le code en image à partir de base64 et chargez-le avec pygame.

La fonction qui charge l'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()

La fonction qui décode le fichier:

def main_uncode(self, object):
    openFile = open(object, "rb")
    str = pickle.load(openFile)
    openFile.close()
    fileData = base64.b64decode(str)
    return fileData

L'erreur que j'obtiens lorsque le code est exécuté:

str = pickle.load(openFile)

EOFError: Ran out of input

Comment puis-je le réparer?

  • Version Python: 3.6.2
  • Version Pygame: 1.9.3

Mise à jour 1

Voici le code que j'ai utilisé pour créer le .obj fichier:

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)

Une fois le fichier créé, il est chargé et une deuxième image est créée. Il s'agit de vérifier si l'image est la même ou s'il y a des erreurs dans la conversion.

Comme vous pouvez le voir, j'ai utilisé une partie du code pour charger l'image, mais au lieu de la sauvegarder, elle est chargée dans pygame. Et c'est là que l'erreur se produit.

Update 2

J'ai finalement réussi à le résoudre.

Dans le code principal:

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")

Dans la bibliothèque contenant les classes graphiques:

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()

Pour la question de savoir pourquoi je devrais faire une telle chose, c'est simple:

tout attaquant avec une motivation suffisante peut toujours y accéder facilement

Python est gratuit et ouvert.

D'une part, nous avons une personne qui va intentionnellement modifier et récupérer les données cachées. Mais si Python est un langage ouvert, comme avec les langages encore plus compliqués et protégés, les plus motivés sont capables de casser le jeu ou le programme et de récupérer les mêmes données.

D'un autre côté, nous avons une personne qui ne connaît que les bases, ou même pas cela. Une personne qui ne peut pas accéder aux fichiers sans en savoir plus sur la langue ou décoder les fichiers.

Vous comprenez donc que le décodage de fichiers, de mon point de vue, n'a pas besoin d'être protégé d'une personne motivée. Parce que même avec une langue plus complexe et protégée, cette personne motivée pourra obtenir ce qu'elle veut. La protection est utilisée contre les personnes qui ne connaissent pas la langue.

7
BlackFenix06

Donc, si l'erreur que vous obtenez est en effet "pickle: run of input", cela signifie que vous avez probablement gâché vos répertoires dans le code ci-dessus et que vous essayez de lire un fichier vide portant le même nom que votre obj le fichier est.

En fait, telle qu'elle est, cette ligne dans votre code:

self.mainTerminal=pg.image.load(path.join(img_main_folder,self.main_uncode
("tr.obj"))).convert_alpha()

Est complètement foiré. Il suffit de le lire et vous pouvez voir le problème: vous passez au main_uncode méthode juste le nom du fichier, sans informations de répertoire. Et puis, si cela avait par hasard fonctionné, comme je l'ai souligné dans les commentaires il y a quelque temps, vous essayez d'utiliser les données d'image non sérialisées comme nom de fichier d'où lire votre image. (Vous ou quelqu'un d'autre aviez probablement pensé que main_uncode devrait écrire un fichier image temporaire et y écrire les données d'image, afin que Pygame puisse le lire, mais en l'état, il ne fait que renvoyer les données d'image brutes dans une chaîne).

Par conséquent, en corrigeant l'appel ci-dessus et en passant un chemin réel vers main_uncode, et le modifier pour écrire les données temporaires dans un fichier et renvoyer son chemin corrigerait les extraits de code ci-dessus.

La deuxième chose est que je ne peux pas comprendre pourquoi vous avez besoin de ce fichier ".obj". Si ce n'est que pour "la sécurité à travers l'obscurité", les gens qui sautent sur votre fichier ne peuvent pas ouvrir les images, c'est loin d'être une pratique recommandée. Pour résumer une seule chose: cela retardera les utilisations légitimes de votre fichier (par exemple, vous ne semblez pas être en mesure de l'utiliser), tandis que tout attaquant avec une motivation suffisante peut toujours y accéder facilement. En ouvrant une image, en l'encodant en base 64 et en la décapant, et en effectuant le processus inverse, vous ne faites pratiquement aucune opération. Encore plus, un fichier pickle peut sérialiser et écrire sur un disque complexe Python objets - mais une sérialisation base64 d'une image peut être écrite directement dans un fichier, sans besoin de pickle.

Troisième chose: utilisez simplement with pour ouvrir tous les fichiers, pas seulement ceux que vous lisez avec la bibliothèque d'imagerie. Prenez votre temps pour en savoir un peu plus sur Python.

2
jsbueno