On Sat, 22 Jan 2005 00:45:19 +1000, Nick Coghlan <[EMAIL PROTECTED]> wrote:
>neutrino wrote: >> Greetings to the Python gurus, >> >> I have a binary file and wish to see the "raw" content of it. So I open >> it in binary mode, and read one byte at a time to a variable, which >> will be of the string type. Now the problem is how to print the binary >> format of that charater to the standard output. It seems a common task >> but I just cannot find the appropriate method from the documentation. >> Thanks a lot. >> > >FWIW, I work with serial data a lot, and I find the following list >comprehension >to be a handy output tool for binary data: > > print " ".join(["%0.2X" % ord(c) for c in data]) > >The space between each byte helps keep things from degenerating into a >meaningless mass of numbers, and using 2-digit hex instead of binary works >towards the same purpose. (I actually currently use the hex() builtin, but the >above just occurred to me, and it will give nicer formatting, and avoids the >C-style "0x" prefixing each byte) > >Here's an interesting twiddle, though (there's probably already something >along >these lines in the cookbook): Looks like you also played with this problem, after Alex posted a request for alternative one-liner solutions to a question on an Italian newsgroup last October? ("show_base" reminded me of "number_in_base") http://groups-beta.google.com/groups?hl=en&lr=&q=number_in_base&qt_s=Search+Groups BTW, my final version was (which can be put on one line ;-) def number_in_base(x, N=10, digits='0123456789ABCDEF'): return '-'[:x<0]+''.join([digits[r] for q in [abs(x)] for q,r in iter(lambda:divmod(q, N), (0,0))][::-1]) or digits[0] (it also takes care of sign and lets you encode with alternative digits if you like ;-) > >Py> def show_base(val, base, min_length = 1): >... chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" >... if base < 2: raise ValueError("2 is minimum meaningful base") >... if base > len(chars): raise ValueError("Not enough characters for base") >... new_val = [] >... while val: >... val, remainder = divmod(val, base) >... new_val.append(chars[remainder]) >... result = "".join(reversed(new_val)) >... return ("0" * (min_length - len(result))) + result Hm, learn something every day ;-) It didn't occur to me that a string multiplied by a negative number would default nicely to the same result as multiplying by zero. >... >Py> show_base(10, 2) >'1010' >Py> show_base(10, 2, 8) >'00001010' >Py> show_base(10, 16, 2) >'0A' >Py> show_base(254, 16, 2) >'FE' >Py> show_base(0, 16) >'0' >Py> for base in range(2, 36): >... for testval in range(1000): >... assert testval == int(show_base(testval, base), base) >... >Py> I guess that's a good idea (supplying full set of alphanumeric digits) >>> def number_in_base(x, N=10, digits='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'): ... return '-'[:x<0]+''.join([digits[r] for q in [abs(x)] ... for q,r in iter(lambda:divmod(q, N), (0,0))][::-1]) or digits[0] ... >>> for base in range(2, 36): ... for testval in range(1000): ... assert testval == int(number_in_base(testval, base), base) ... >>> For that matter, might as well go for Z base and negatives too: >>> for base in range(2, 37): ... for testval in range(-500, 500): ... assert testval == int(number_in_base(testval, base), base) ... >>> (assert did not complain) >>> for base in range(2, 37): ... for testval in (-base+2, -base+1, -base, base-2, base-1,base): ... print '%4s:%-4s'%(testval, number_in_base(testval, base)), ... print ... 0:0 -1:-1 -2:-10 0:0 1:1 2:10 -1:-1 -2:-2 -3:-10 1:1 2:2 3:10 -2:-2 -3:-3 -4:-10 2:2 3:3 4:10 -3:-3 -4:-4 -5:-10 3:3 4:4 5:10 -4:-4 -5:-5 -6:-10 4:4 5:5 6:10 -5:-5 -6:-6 -7:-10 5:5 6:6 7:10 -6:-6 -7:-7 -8:-10 6:6 7:7 8:10 -7:-7 -8:-8 -9:-10 7:7 8:8 9:10 -8:-8 -9:-9 -10:-10 8:8 9:9 10:10 -9:-9 -10:-A -11:-10 9:9 10:A 11:10 -10:-A -11:-B -12:-10 10:A 11:B 12:10 -11:-B -12:-C -13:-10 11:B 12:C 13:10 -12:-C -13:-D -14:-10 12:C 13:D 14:10 -13:-D -14:-E -15:-10 13:D 14:E 15:10 -14:-E -15:-F -16:-10 14:E 15:F 16:10 -15:-F -16:-G -17:-10 15:F 16:G 17:10 -16:-G -17:-H -18:-10 16:G 17:H 18:10 -17:-H -18:-I -19:-10 17:H 18:I 19:10 -18:-I -19:-J -20:-10 18:I 19:J 20:10 -19:-J -20:-K -21:-10 19:J 20:K 21:10 -20:-K -21:-L -22:-10 20:K 21:L 22:10 -21:-L -22:-M -23:-10 21:L 22:M 23:10 -22:-M -23:-N -24:-10 22:M 23:N 24:10 -23:-N -24:-O -25:-10 23:N 24:O 25:10 -24:-O -25:-P -26:-10 24:O 25:P 26:10 -25:-P -26:-Q -27:-10 25:P 26:Q 27:10 -26:-Q -27:-R -28:-10 26:Q 27:R 28:10 -27:-R -28:-S -29:-10 27:R 28:S 29:10 -28:-S -29:-T -30:-10 28:S 29:T 30:10 -29:-T -30:-U -31:-10 29:T 30:U 31:10 -30:-U -31:-V -32:-10 30:U 31:V 32:10 -31:-V -32:-W -33:-10 31:V 32:W 33:10 -32:-W -33:-X -34:-10 32:W 33:X 34:10 -33:-X -34:-Y -35:-10 33:X 34:Y 35:10 -34:-Y -35:-Z -36:-10 34:Y 35:Z 36:10 >>> Of course, this is the prefixed-sign and absolute value representation, which is no good if you are using base 2, 8, or 16 to get an idea of underlying bits in a negative two-s complement representation. But that's another thread ;-) Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list