Discussion:
Unpacking a hex value
Peter Hansen
2002-05-18 02:11:34 UTC
Permalink
$out = pack("N", $out);
However, I can't figure out how to pack the hex value. I always get an
error: "required argument is not an integer". Python's pack doesn't have
an "N" format, but I think I could use "l!" Help? Please?
Please post your code and the exception traceback so we can tell what
the problem is directly, rather than guessing.
import struct
struct.pack('l', '5')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
struct.error: required argument is not an integer
struct.pack('l', 5)
'\x05\x00\x00\x00'

And you know about the documentation for struct, right? It tells
what "l" means, and the others. And did you really mean "!l"?

http://www.python.org/doc/current/lib/module-struct.html

-Peter
Peter Hansen
2002-05-18 04:18:14 UTC
Permalink
def hex2bin(input)
output = hex( input )
output = pack("!l", output)
...
From this, I get the error "required argument is not an integer", as
previously stated. There's no other info in the Traceback that's
important. I've tried wrapping output with a call to the int() function,
but that doesn't work either.
Well, hex() returns a string, not an integer. The error message is
telling you that an argument to struct.pack() needs to be an integer
but is not. So why use hex()?

The input to int() must be a decimal integer string, not a hexadecimal
one, so you get the "invalid literal for int()" message, presumably.
You could use int(output, 16) instead, which knows about the leading
"0x" in the string and skips it, or you could just pass the integer
"input" directly to the pack statement...

I get the impression you are trying to do something slightly
different than what either of these solutions gives you, so maybe
you could give examples of input and desired output if that doesn't
solve your problems.
You did get me on the "!l" instead of "l!", but it didn't specify order
in the struct docs, so I was guessing.
It is a little hard to find, but:

"Alternatively, the first character of the format string can be used
to indicate the byte order, size and alignment of the packed data,
according to the following table:" [table snipped]

-Peter
Paul Rubin
2002-05-18 15:17:54 UTC
Permalink
Please look at the binascii module to see if it has a function that
does what you want. It's a C extension so it will run much faster
than writing your own function in Python.
Matthew Diephouse
2002-05-18 14:00:02 UTC
Permalink
Post by Peter Hansen
I get the impression you are trying to do something slightly
different than what either of these solutions gives you, so maybe
you could give examples of input and desired output if that doesn't
solve your problems.
-Peter
OK. I'm trying to open and decode some binary files. In order to do get
the data, I need to break up parts of them into 1's and 0's, so I have a
function hex2bin() that transform some of the data from hex to 1's and
0's. I already have Perl code to do this, which I'll put below.

There are a couple things that are messing me up. Many of them are from
pack/unpack, though some come from the differences between perl/ruby and
python. Pack/unpack don't accept the format "H*", or the number of chars
that I'm getting out of the perl functions.

sub hex2bin { # For example data,
my $out = hex( shift(@_) ); # $out = 21847 (after command)
$out = pack("N", $out); # $out = UW
$out = unpack("B32", $out);
# $out = 00000000000000000101010101010111
$out = substr $out, -16, 16; # $out = 0101010101010111
return split "", $out;
}

There's my function in perl. What I've been trying in python is:

def hex2bin(input):
output = int( input, 16)
output = pack("!l", output)
output = unpack("B" * (len(input) / calcsize("B")), output)
# ----------------^
# "B32" gives me an error

print output
output = output[-16:16]
return output.split("")

So how should the python code look?

md |- m:att d:iephouse
Bengt Richter
2002-05-18 09:08:29 UTC
Permalink
The code is very much like the Perl code I submitted. It is within a
subroutine.
def hex2bin(input)
output = hex( input )
output = pack("!l", output)
...
From this, I get the error "required argument is not an integer", as
previously stated. There's no other info in the Traceback that's
important. I've tried wrapping output with a call to the int() function,
but that doesn't work either.
You did get me on the "!l" instead of "l!", but it didn't specify order
in the struct docs, so I was guessing.
Notice that hex in perl and python effectively are inverses of each other:

[ 1:47] C:\pywk>python -c "print hex(65539)"
0x10003

[ 1:47] C:\pywk>perl -e "print hex('0x10003')"
65539

So if I understand right I would guess you need something like
from struct import pack
... output = int( input, 16) # makes 32-bit native int from hex string
... output = pack("!l", output) # takes native int and packs its bytes into 'network' order string
... return output
...
hex2bin('12345678')
'\x124Vx'
['%02X' % ord(x) for x in hex2bin('12345678')] # hex values of char seq generated
['12', '34', '56', '78']

Which you can see is the hex values of the characters of the above '\x124Vx' in order,
[chr(int(x,16),) for x in ['12', '34', '56', '78']]
['\x12', '4', 'V', 'x']
... output = int( input, 16)
... output = pack("l", output)
... return output
...
hex2bin('12345678')
'xV4\x12'
['%02X' % ord(x) for x in hex2bin('12345678')]
['78', '56', '34', '12']
[chr(int(x,16),) for x in ['78', '56', '34', '12']]
['x', 'V', '4', '\x12']

Regards,
Bengt Richter
Matthew Diephouse
2002-05-18 01:04:05 UTC
Permalink
I have the following perl code, which I'm trying to translate to python:

my $out = hex( shift(@_) );
$out = pack("N", $out);

However, I can't figure out how to pack the hex value. I always get an
error: "required argument is not an integer". Python's pack doesn't have
an "N" format, but I think I could use "l!" Help? Please?

md |- m:att d:iephouse
Paul Rubin
2002-05-18 06:02:58 UTC
Permalink
$out = pack("N", $out);
Maybe I don't understand this, but if you're trying to convert a hex string
to a binary string, use:

import binascii
out = binascii.unhexlify(hex_string)
Matthew Diephouse
2002-05-18 02:36:51 UTC
Permalink
The code is very much like the Perl code I submitted. It is within a
subroutine.

def hex2bin(input)
output = hex( input )
output = pack("!l", output)
...

From this, I get the error "required argument is not an integer", as
previously stated. There's no other info in the Traceback that's
important. I've tried wrapping output with a call to the int() function,
but that doesn't work either.

You did get me on the "!l" instead of "l!", but it didn't specify order
in the struct docs, so I was guessing.
Post by Peter Hansen
$out = pack("N", $out);
However, I can't figure out how to pack the hex value. I always get an
error: "required argument is not an integer". Python's pack doesn't have
an "N" format, but I think I could use "l!" Help? Please?
Please post your code and the exception traceback so we can tell what
the problem is directly, rather than guessing.
import struct
struct.pack('l', '5')
File "<stdin>", line 1, in ?
struct.error: required argument is not an integer
struct.pack('l', 5)
'\x05\x00\x00\x00'
And you know about the documentation for struct, right? It tells
what "l" means, and the others. And did you really mean "!l"?
http://www.python.org/doc/current/lib/module-struct.html
-Peter
Chris Liechti
2002-05-18 02:54:08 UTC
Permalink
Matthew Diephouse <fokke_wulf at hotmail.com> wrote in
The code is very much like the Perl code I submitted. It is within a
subroutine.
def hex2bin(input)
output = hex( input )
output = pack("!l", output)
...
if you want to convert a number to a string containing the binary
represenation of the number try it without hex():

def hex2bin(inp)
output = pack("!l", inp)
...

hex() in python converts number->string. if the input above is a string
with hexdigits use int() instead:
output = pack("!l", int(inp,16))
or if you need to cut away '0x'
output = pack("!l", int(inp[2:],16))

chris
From this, I get the error "required argument is not an integer", as
previously stated. There's no other info in the Traceback that's
important. I've tried wrapping output with a call to the int() function,
but that doesn't work either.
--
Chris <cliechti at gmx.net>
Loading...