Index: Lib/pickletools.py =================================================================== --- Lib/pickletools.py (revision 82911) +++ Lib/pickletools.py (working copy) @@ -1904,7 +1904,7 @@ ############################################################################## # A symbolic pickle disassembler. -def dis(pickle, out=None, memo=None, indentlevel=4): +def dis(pickle, out=None, memo=None, indentlevel=4, annotate=0): """Produce a symbolic disassembly of a pickle. 'pickle' is a file-like object, or string, containing a (at least one) @@ -2017,6 +2017,12 @@ line += ' ' + repr(arg) if markmsg: line += ' ' + markmsg + if annotate: + line += ' ' * (annotate - len(line)) + # make a mild effort to align annotations + annotate = len(line) + line += ' | ' + line += opcode.doc.split('\n', 1)[0] print(line, file=out) if errormsg: @@ -2290,6 +2296,22 @@ 12: h BINGET 1 14: . STOP highest protocol among opcodes = 2 + +Try protocol 3 with annotations: + +>>> dis(pickle.dumps(T, 3), annotate=1) + 0: \x80 PROTO 3 | Protocol version indicator. + 2: ] EMPTY_LIST | Push an empty list. + 3: q BINPUT 0 | Store the stack top into the memo. The stack is not popped. + 5: h BINGET 0 | Read an object from the memo and push it on the stack. + 7: \x85 TUPLE1 | One-tuple. + 8: q BINPUT 1 | Store the stack top into the memo. The stack is not popped. + 10: a APPEND | Append an object to a list. + 11: 0 POP | Discard the top stack item, shrinking the stack by one item. + 12: h BINGET 1 | Read an object from the memo and push it on the stack. + 14: . STOP | Stop the unpickling machine. +highest protocol among opcodes = 2 + """ _memo_test = r""" @@ -2346,6 +2368,9 @@ '-l', '--indentlevel', default=4, type=int, help='the number of blanks by which to indent a new MARK level') parser.add_argument( + '-a', '--annotate', action='store_true', + help='annotate each line with a short opcode description') + parser.add_argument( '-p', '--preamble', default="==> {name} <==", help='if more than one pickle file is specified, print this before' ' each disassembly') @@ -2359,14 +2384,15 @@ if args.test: _test() else: + annotate = 30 if args.annotate else 0 if not args.pickle_file: parser.print_help() elif len(args.pickle_file) == 1: - dis(args.pickle_file[0], args.output, - indentlevel=args.indentlevel) + dis(args.pickle_file[0], args.output, None, + args.indentlevel, annotate) else: memo = {} if args.memo else None for f in args.pickle_file: preamble = args.preamble.format(name=f.name) args.output.write(preamble + '\n') - dis(f, args.output, memo, args.indentlevel) + dis(f, args.output, memo, args.indentlevel, annotate)