2016-12-26 14 views
1

私はPythonが初めてで、私の最初のプロジェクトとして、Python2のスクリプトをPython3に変換しようとしています。Python3 pickle serialization with Cmd

スクリプトは、pickleを使用してクラスをシリアライズしようとすると失敗します。

Cmd CLIを使用するクラスを保存しようとしているように見えているようです。

このコードはPython2を使用して動作します。

スクリプトに何が間違っているか教えてもらえますか?

import sys 
import cmd 

try: 
    import pickle as pickle 
except: 
    import pickle 
import os.path 

def main():  

     app = Labyrinth() 
     turnfile = "turn0.lwot" 
     app.Save(turnfile) 

class CLI(cmd.Cmd): 
    def __init__(self): 
     cmd.Cmd.__init__(self) 

class Labyrinth(cmd.Cmd): 

    def __init__(self): 
     cmd.Cmd.__init__(self) 

    def Save(self, fname): 
     with open(fname, 'wb') as f: 
      pickle.dump(self,f, 2) 
     f.close() 
     print ("Save Successful!") 
     sys.exit() 

if __name__ == '__main__': 
    main() 
+0

try/exceptで囲まれたピクルスとしてのインポートピクルスとは何ですか? –

+0

@Turry - それはPython 2の誤った 'pickle as pickle 'だと思っています。 – tdelaney

答えて

0

プロトコルで遊ぶことは役に立ちません。 (あなたが含まれているはずです)完全なエラーメッセージは次のとおりです。

1027:~/mypy$ python3 stack41334887.py 
Traceback (most recent call last): 
    File "stack41334887.py", line 33, in <module> 
    main() 
    File "stack41334887.py", line 14, in main 
    app.Save(turnfile) 
    File "stack41334887.py", line 27, in Save 
    pickle.dump(self,f, 3, fix_imports=True) 
TypeError: cannot serialize '_io.TextIOWrapper' object 

のpython3 ioシステムのいくつかの主要な変更を行いました。このTextIOWrapperは、私はPy3の初心者だと思います。

https://docs.python.org/3.1/library/io.html#io.TextIOWrapper

Can I use multiprocessing.Pool in a method of a class?TextIOWrapperをシリアル化の問題を抱えていました。だから、@tdelaneyによってinspireed

=========

は、私は私のPY3セッションのためにstdinチェック:

In [1212]: sys.stdin 
Out[1212]: <_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'> 

だからそれをシリアル化することはできないことです。

2

すべてのオブジェクトがpicklableであるわけではありません。特に、後で状態を通常復元することはできないため、ファイルオブジェクトには問題があります。 cmd.Cmdは、stdinstdoutのファイルオブジェクトを保持しているため、それらをunpicklableにする必要があります。私はそれがpythonの2に働いたことは非常に驚きましたが、それは本当に...でもstdinstdout漬けても、後で取り戻すunpickle化オブジェクトは、この例のように、動作しませんしませんでした:

>>> import sys 
>>> import pickle 
>>> sys.stdout.write('foo\n') 
foo 
>>> serialized = pickle.dumps(sys.stdout, 2) 
>>> stdout = pickle.loads(serialized) 
>>> stdout.write('bar\n') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: I/O operation on closed file 
>>> 

このコードは失敗しませんでしたが、オブジェクトを後で使用できないようにする必要があります。オブジェクトにいくつかの特別なメソッドを追加して、オブジェクトをシリアル化できるように修正することができます。ここでは、保存時に悪い属性を取り除き、復元時にそれらを追加しました。これでピクル、アンピクルができます。

import sys 
import cmd 

try: 
    import cPickle as pickle 
except: 
    import pickle 
import os.path 

def main():  

     app = Labyrinth() 
     turnfile = "turn0.lwot" 
     app.Save(turnfile) 

class CLI(cmd.Cmd): 
    def __init__(self): 
     cmd.Cmd.__init__(self) 

class Labyrinth(cmd.Cmd): 

    def __init__(self): 
     cmd.Cmd.__init__(self) 

    def Save(self, fname): 
     with open(fname, 'wb') as f: 
      pickle.dump(self,f, pickle.HIGHEST_PROTOCOL) 
     f.close() 
     print ("Save Successful!") 
     sys.exit() 

    def __getstate__(self): 
     # stdin/out are unpicklable. We'll get new ones on load 
     return tuple(((k,v) for k,v in self.__dict__.items() 
      if k not in ('stdin', 'stdout'))) 

    def __setstate__(self, state): 
     self.__dict__.update(state) 
     self.stdin = sys.stdin 
     self.stdout = sys.stdout 


if __name__ == '__main__': 
    main() 
+0

ありがとうございます、それはうまく動作し、私はプロセスでPython picklingとunpicklingについて公正なビットを学びました。 – gasha1

関連する問題