5

Python文字列をフィールドに展開する最良の方法は何ですか?

TCPソケットから受信したデータがあります。次のようにパックされています。ソケットのrecv関数からの文字列になると思います

次の形式です。

uint8 - ヘッダー
uint8 - 長さ
uint32 - タイプ ID
uint16 -param1
uint16 -param2
uint16 -param3
uint16 -param4
char[24] - 名前文字列
uint32 - チェックサム
uint8 - フッター

(上記とは異なる形式の他のパケットも解凍する必要があります)

これらを開梱するにはどうすればよいですか?

私はPythonが初めてで、「C」を少しやったことがあります。「C」を使用していた場合、おそらく構造体を使用するでしょうが、これは Python で使用する方法でしょうか?

よろしく

バツ

4

5 に答える 5

6

struct モジュールは、フォーマット文字列に基づいて異種データをタプルにアンパックするように設計されています。一度に 1 つのフィールドを取り出すよりも、構造体全体を一度に展開する方が理にかなっています。次に例を示します。

fields = struct.unpack('!BBI4H20sIB', data)

次に、最初のフィールドなど、特定のフィールドにアクセスできます。

fields[0]

タプルを使用して NamedTuple を初期化することもできます。例については、構造体のドキュメントを参照してください。NamedTuples は Python 2.6+ でのみ使用できますが、fields.header などの属性として要素にアクセスできるという点で、Python 構造のように動作します。もちろん、タプルからの情報をカプセル化するクラスを作成することで、もう少し作業を行うことでこれを実現することもできます。上で示したように、いつでもフィールドに直接インデックスを付けることができます。

于 2009-12-10T12:09:30.273 に答える
4

structモジュールを使用

于 2009-12-10T09:55:12.833 に答える
4

これは、回答としての質問に対する回答です。

それはうまくいかないので、確かに最善の方法ではありません。struct.unpack()常にタプルを返します。そのタプルから 1 つの項目を取り出すには、 または のいずれかを実行する必要がありfield1 = struct.unpack('B',data[0])[0]ますfield1, = struct.unpack('B',data[0])

その修正を行っても、それは良い方法ではありません: 入力が多すぎる、不要な [start:end] のエラーが発生しやすい、1 回ではなく 10 回の関数呼び出しの非効率性。

名前があるので、field1 または field[0] の代わりにそれらを使用できます ... 次のように:

(header, length, typeID, param1, param2,
param3, param4, name_string, checksum, footer,
) = struct.unpack("!2B I 4H 24s I B", data)
于 2009-12-10T13:09:30.503 に答える
1

これはこれを行うための最良の方法ですか、それともより良い方法がありますか

別のアンパック スキームを必要とする他の形式の文字列が存在する可能性があります。

field1 = struct.unpack('B',data[0])
field2 = struct.unpack('B',data[1])
field3 = struct.unpack('!I',data[2:6])
field4 = struct.unpack('!H',data[6:8])
field5 = struct.unpack('!H',data[8:10])
field6 = struct.unpack('!H',data[10:12] ])
field7 = struct.unpack('!H',data[12:14])
field8 = struct.unpack('20s',data[14:38])
field9 = struct.unpack('!I',data[ 38:42])
field10 = struct.unpack('B',data[42])

よろしく

于 2009-12-10T11:41:50.950 に答える
0

モジュール ' struct ' を見てください。

于 2009-12-10T09:57:43.227 に答える