web-dev-qa-db-ja.com

pickle.load-EOFError:入力が不足しています

以前に画像をbase64に変換し、pickleで保存した.objファイルがあります。

問題は、.objファイルをpickleでロードし、コードをbase64からイメージに変換し、pygameでロードしようとするときです。

画像をロードする関数:

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

ファイルをデコードする関数:

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

コードを実行するとエラーが発生します:

str = pickle.load(openFile)

EOFError:入力が不足しています

どうすれば修正できますか?

  • Pythonバージョン:3.6.2
  • Pygameバージョン:1.9.3

アップデート1

これは、.objファイルの作成に使用したコードです。

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)

ファイルが作成されると、そのファイルがロードされ、2番目のイメージが作成されます。これは、イメージが同じであるか、変換にエラーがあるかどうかを確認することです。

ご覧のとおり、画像の読み込みにはコードの一部を使用しましたが、保存する代わりにpygameに読み込まれます。そして、それは間違いが発生する場所です。

更新2

やっと解決できました。

メインコードで:

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

グラフィッククラスを含むライブラリ内:

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

なぜそんなことをするのかという質問については、簡単です。

十分な動機を持つ攻撃者は、まだ簡単に到達できます

Pythonは無料でオープンです。

一方では、意図的に非表示のデータを変更および回復する人がいます。しかし、もしPythonがより複雑で保護された言語のようにオープン言語であるなら、最もやる気のある人はゲームやプログラムをクラックして同じデータを取得することができます。

一方、基本だけを知っている人もいれば、それさえ知らない人もいます。言語について詳しく知らない、またはファイルをデコードせずにファイルにアクセスできない人。

したがって、私の観点からは、ファイルのデコードはやる気のある人から保護する必要がないことを理解できます。より複雑で保護された言語であっても、そのやる気のある人は自分が望むものを手に入れることができるからです。保護は、言語を知らない人々に対して使用されます。

7
BlackFenix06

したがって、エラーが「pickle:run out of input」である場合、上記のコードでディレクトリを台無しにして、objと同じ名前の空のファイルを読み取ろうとしている可能性があります。ファイルは。

実際、コードの次の行はそのままです:

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

完全に台無しにされています。読むだけで問題を確認できます。ディレクトリ情報なしでファイル名だけをmain_uncodeメソッドに渡します。そして、先ほどコメントで述べたように、たまたまうまくいった場合は、シリアル化されていない画像データを画像の読み取り元のファイル名として使用してみます。 (あなたや他の誰かがおそらくmain_uncodeは一時的な画像ファイルを書き、それに画像データを書き込むべきだと思っていたので、Pygameはそれを読むことができますが、それはそのままで生の画像データを返すだけですストリング)。

したがって、上記の呼び出しを修正して実際のパスをmain_uncodeに渡し、さらに一時データをファイルに書き込んでそのパスを返すようにさらに変更すると、上記のコードのスニペットが修正されます。

2番目の理由は、なぜこの ".obj"ファイルが必要なのかまったくわかりません。バンドルされたファイルが画像を開けないようにするための「隠蔽によるセキュリティ」だけを目的とする場合、これは推奨される方法とはほど遠いものです。 1つだけをまとめると、ファイルの正当な使用を遅らせます(たとえば、あなた自身はそれを使用できないようです)が、十分な動機を持った攻撃者はそれでも簡単にアクセスできます。画像を開いて、base-64エンコードとピクルスを行い、逆のプロセスを実行することで、基本的に何も操作しません。さらに、pickleファイルはシリアル化してディスクコンプレックスに書き込むことができますPythonオブジェクト-ただし、base64による画像のシリアル化は、pickleを必要とせずにファイルに直接書き込むことができます。

3番目:イメージングライブラリで読み込んだファイルだけでなく、withを使用してすべてのファイルを開くだけです。Pythonについてもう少し学んでください。

2
jsbueno