4

ピクルスで悩んでいます。OSX と Linux の間では問題なく動作しますが、Windows と Linux ではうまくいきません。pickle 化された文字列はすべてメモリに保存され、SSL ソケット経由で送信されます。100% 明確にするために、すべての '\n' を ":::" に、すべての '\r' を "===" に置き換えました (何もありませんでした)。シナリオ:

  • Client-Win: Python 2.7 を実行する Small Business Server 2011
  • Client-Lin: Python 2.7 を実行する Fedora Linux
  • サーバー: Python 2.7 を実行する Fedora Linux

Client-Lin は pickled オブジェクトをサーバーに送信します。

ccopy_reg:::_reconstructor:::p0:::(c__main__:::infoCollection:::p1:::c__builtin__:::tuple:::p2:::(VSTRINGA:::p3:::VSTRINGB:::p4:::VSTRINGC:::p5:::tp6:::tp7:::Rp8:::.

Client-Win は、選択したオブジェクトをサーバーに送信します。

ccopy_reg:::_reconstructor:::p0:::(c__main__:::infoCollection:::p1:::c__builtin__:::tuple:::p2:::(VSTRINGA:::p3:::VSTRINGB:::p4:::VSTRINGC:::p5:::tp6:::tp7:::Rp8:::ccollections:::OrderedDict:::p9:::((lp10:::(lp11:::S'string_a':::p12:::ag3:::aa(lp13:::S'string_b':::p14:::ag4:::aa(lp15:::S'string_c':::p16:::ag5:::aatp17:::Rp18:::b.

何らかの理由で、Windows クライアントは pickle とともに追加情報を送信し、Linux クライアントが pickle 文字列を読み込もうとすると、次のようになります。

Unhandled exception in thread started by <function TestThread at 0x107de60>
Traceback (most recent call last):
  File "./test.py", line 212, in TestThread
    info = pickle.loads(p_string)
  File "/usr/lib64/python2.7/pickle.py", line 1382, in loads
    return Unpickler(file).load()
  File "/usr/lib64/python2.7/pickle.py", line 858, in load
    dispatch[key](self)
  File "/usr/lib64/python2.7/pickle.py", line 1224, in load_build
    d = inst.__dict__
AttributeError: 'infoCollection' object has no attribute '__dict__'

何か案は?

EDIT 追加の要求された情報を追加します。

infoCollection クラスは同じ方法で定義されます。

infoCollection = collections.namedtuple('infoCollection', 'string_a, string_b, string_c')

def runtest():
    info = infoCollection('STRINGA', 'STRINGB', 'STRINGC')
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    ssl_sock = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
    ssl_sock.connect((server, serverport))
    ssl_sock.write(pickle.dumps(info))
    ssl_sock.close()

受信機能はほぼ同じですが、

p_string = ssl_sock.read()
info = pickle.loads(p_string)
4

5 に答える 5

2

ハックですが、クロスプラットフォームの問題は、クロスプラットフォーム環境での名前付きタプルとピクルの組み合わせが原因のようです。namedtuple を自分のクラスに置き換えたところ、すべてうまくいきました。

class infoClass(object):
    pass

def infoCollection(string_a, string_b, string_c):
    i = infoClass()
    i.string_a = string_a
    i.string_b = string_b
    i.string_c = string_c
    return i
于 2013-02-19T14:53:33.640 に答える
0

あなたが

p_string = ssl_sock.read(nbytes=1.0E6)
info = pickle.loads(p_string)
于 2013-02-19T15:04:49.537 に答える
0

バイナリ pickle ファイルとして保存しようとしましたか?

with open('pickle.file', 'wb') as po:
    pickle.dump(obj, po)

また、さまざまなOS間で移植している場合、およびJSONを見たinfoだけの場合(一般的にはJSONよりも安全と考えられています)?namedtuplepickle

with open('pickle.json', 'w') as po:
    json.dump(obj, po)

編集ssl .read() ドキュメント から、.read()デフォルトでは最大1024バイトしか読み取れないようですが、 infonamedtupleがそれよりも大きくなることに賭けます。アプリオリにどれだけ大きいかを知るのinfoは難しいでしょう。設定だけでうまくいくかどうかはわかりません(おそらくそうではないと思います)。nbytes=HUGE NUMBER

于 2013-02-19T14:35:40.537 に答える