Egehan AVCU
Egehan AVCU

Reputation: 13

Struct Unpack with Variable

I am trying to convert my code to Python 3 and I am having a problem about Struct while using problem. When I don't use variable while unpacking it gives me the result which I want, but when I use variable it doesn't give me the result that it needs to give.

I use def named "dataReceived" to get the data from socket. And I unpack it with struct.

Code with no variable (it gives true result) (result is 2) (packet is same with the packet that I get from socket):

packetFormat = unpack('!b', b'\x02\x01]\x00\x1c\x01\x01\xb0\x00\taMtIyfKal\x00\x07ActiveX\x00\x165.0 (Windows)-Netscape\x00)\xed\x06\x00\x00\x00@3407d2fbeefadbf85fa0f48bbac8337e026e0669b6be226156fd6fb4d575ef16\x00\xd9A=t&SA=t&SV=t&EV=t&MP3=t&AE=t&VE=t&ACC=t&PR=t&SP=f&SB=f&DEB=f&V=WIN 28,0,0,137&M=Adobe Windows&R=1280x1024&COL=color&AR=1.0&OS=Windows 8&ARCH=x86&L=tr&IME=t&PR32=t&PR64=t&PT=ActiveX&AVD=f&LFD=f&WD=f&TLS=t&ML=5.1&DP=72\x00\x00\x00\x00\x00\x00\x02\xca\x00\x00'[:1])[0]
print(packetFormat)

Code with variable (Gets the packet from def dataReceived) (it gives false result) (result is 98) (and both packets are same)

def dataReceived(this, packet):
    this.package = str(packet)
    packetFormat = unpack('!b', bytes(this.package, "utf-8")[:1])[0]

Upvotes: 2

Views: 1050

Answers (1)

snakecharmerb
snakecharmerb

Reputation: 55589

Calling str on the bytes value that you receive does not do what you think it does.

This is the old, good, behaviour:

>>> bs = b'\x02'
>>> struct.unpack('!b', bs)
(2,)

In the new code, the bytes value is cast to a string:

>>> s = str(bs)

then it's unpacked:

>>> struct.unpack('!b', bytes(s, 'utf-8'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
struct.error: unpack requires a bytes object of length 1

Looks like there is something strange about the string value:

>>> s
"b'\\x02'"
>>> struct.unpack('!b', bytes(s, 'utf-8')[:1])
(98,)

Calling str on a bytes value gives us the bytes' repr as a string; to get the bytes as a string we need to call the bytes value's decode method. Note that your packet data appears to be encoded as latin-1, not utf-8. This doesn't matter for the first byte, but it does if you want to decode the entire bytestring.

>>> s = bs.decode('latin-1')
>>> struct.unpack('!b', bytes(s, 'latin-1'))
(2,)

So, don't call str on the bytes value that you unpack, either decode it or, better still, just leave it as bytes and avoid the unnecessary encoding and decoding. You can decode the bytes to a unicode string and store them on your instance though.

def dataReceived(this, packet):
    this.package = packet.decode('latin-1')  # Store packet data as a unicode string
    packetFormat = unpack('!b', packet[:1])[0]

Upvotes: 3

Related Questions