Augment dis.dis to autocompile strings
![](https://secure.gravatar.com/avatar/d6b9415353e04ffa6de5a8f3aaea0553.jpg?s=120&d=mm&r=g)
Currently "dis.dis(x=None) Disassemble the x object. x can denote either a module, a class, a method, a function, or a code object. " The behavior depends on the class of x, so dis already has an internal switch. Currently, to see the assembly equivalent of CPython bytecode for a small snippet, one must either wrap it in a function or *remember* the exact idiom: compile("while True: break", "", "exec") Proposal: if the input is a string, do the above (do what I mean) instead of raising TypeError: don't know how to disassemble str objects Any negatives before I submit a feature request? Terry Jan Reedy
![](https://secure.gravatar.com/avatar/f3ba3ecffd20251d73749afbfa636786.jpg?s=120&d=mm&r=g)
Terry Reedy wrote:
Currently "dis.dis(x=None) Disassemble the x object. x can denote either a module, a class, a method, a function, or a code object. "
The behavior depends on the class of x, so dis already has an internal switch.
Currently, to see the assembly equivalent of CPython bytecode for a small snippet, one must either wrap it in a function or *remember* the exact idiom: compile("while True: break", "", "exec")
Proposal: if the input is a string, do the above (do what I mean) instead of raising TypeError: don't know how to disassemble str objects
Any negatives before I submit a feature request?
Not that I can see. +1. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
![](https://secure.gravatar.com/avatar/5615a372d9866f203a22b2c437527bbb.jpg?s=120&d=mm&r=g)
On Fri, 17 Jul 2009 04:35:40 am Terry Reedy wrote:
Proposal: if the input is a string, do the above (do what I mean) instead of raising TypeError: don't know how to disassemble str objects
Any negatives before I submit a feature request?
+1 on the idea, but how do you determine which of the following are required? compile('x+1', '', 'eval') compile('x = x+1', '', 'single') compile('while x < 42: x += 1', '', 'exec') Or do you just assume 'exec'? -- Steven D'Aprano
![](https://secure.gravatar.com/avatar/d6b9415353e04ffa6de5a8f3aaea0553.jpg?s=120&d=mm&r=g)
Steven D'Aprano wrote:
On Fri, 17 Jul 2009 04:35:40 am Terry Reedy wrote:
Proposal: if the input is a string, do the above (do what I mean) instead of raising TypeError: don't know how to disassemble str objects
Any negatives before I submit a feature request?
+1 on the idea, but how do you determine which of the following are required?
compile('x+1', '', 'eval') compile('x = x+1', '', 'single') compile('while x < 42: x += 1', '', 'exec')
Or do you just assume 'exec'?
Good question. Let us see what difference it makes in 3.1
dis(compile('x+1','', 'eval')) 1 0 LOAD_NAME 0 (x) 3 LOAD_CONST 0 (1) 6 BINARY_ADD 7 RETURN_VALUE
dis(compile('x+1', '', 'exec')) 1 0 LOAD_NAME 0 (x) 3 LOAD_CONST 0 (1) 6 BINARY_ADD 7 POP_TOP 8 LOAD_CONST 1 (None) 11 RETURN_VALUE
Adds an extra POP_TOP and LOAD_CONST None
dis(compile('x = x+1', '', 'single')) 1 0 LOAD_NAME 0 (x) 3 LOAD_CONST 0 (1) 6 BINARY_ADD 7 STORE_NAME 0 (x) 10 LOAD_CONST 1 (None) 13 RETURN_VALUE
dis(compile('x = x+1', '', 'exec')) 1 0 LOAD_NAME 0 (x) 3 LOAD_CONST 0 (1) 6 BINARY_ADD 7 STORE_NAME 0 (x) 10 LOAD_CONST 1 (None) 13 RETURN_VALUE
No difference I decided to submit this to the tracker. http://bugs.python.org/issue6507 Terry Jan Reedy
![](https://secure.gravatar.com/avatar/f3ba3ecffd20251d73749afbfa636786.jpg?s=120&d=mm&r=g)
Steven D'Aprano wrote:
On Fri, 17 Jul 2009 04:35:40 am Terry Reedy wrote:
Proposal: if the input is a string, do the above (do what I mean) instead of raising TypeError: don't know how to disassemble str objects
Any negatives before I submit a feature request?
+1 on the idea, but how do you determine which of the following are required?
compile('x+1', '', 'eval') compile('x = x+1', '', 'single') compile('while x < 42: x += 1', '', 'exec')
Or do you just assume 'exec'?
We could define it as trying the three in order (first 'eval', then 'single', then 'exec') moving on to the next option if it raises syntax error: from dis import dis def dis_str(source): modes = ('eval', 'single', 'exec') for mode in modes: try: c = compile(source, '', mode) break except SyntaxError: if mode is modes[-1]: raise return dis(c)
dis_str("x+1") 1 0 LOAD_NAME 0 (x) 3 LOAD_CONST 0 (1) 6 BINARY_ADD 7 RETURN_VALUE dis_str("x = x+1") 1 0 LOAD_NAME 0 (x) 3 LOAD_CONST 0 (1) 6 BINARY_ADD 7 STORE_NAME 0 (x) 10 LOAD_CONST 1 (None) 13 RETURN_VALUE dis_str("while x < 42: x += 1") 1 0 SETUP_LOOP 26 (to 29) >> 3 LOAD_NAME 0 (x) 6 LOAD_CONST 0 (42) 9 COMPARE_OP 0 (<) 12 POP_JUMP_IF_FALSE 28 15 LOAD_NAME 0 (x) 18 LOAD_CONST 1 (1) 21 INPLACE_ADD 22 STORE_NAME 0 (x) 25 JUMP_ABSOLUTE 3 >> 28 POP_BLOCK >> 29 LOAD_CONST 2 (None) 32 RETURN_VALUE dis_str("bad syntax still goes boom") Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 5, in dis_str File "", line 1 bad syntax still goes boom ^ SyntaxError: invalid syntax
Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
![](https://secure.gravatar.com/avatar/2fc5b058e338d06a8d8f8cd0cfe48376.jpg?s=120&d=mm&r=g)
Nick Coghlan schrieb:
Steven D'Aprano wrote:
On Fri, 17 Jul 2009 04:35:40 am Terry Reedy wrote:
Proposal: if the input is a string, do the above (do what I mean) instead of raising TypeError: don't know how to disassemble str objects
Any negatives before I submit a feature request?
+1 on the idea, but how do you determine which of the following are required?
compile('x+1', '', 'eval') compile('x = x+1', '', 'single') compile('while x < 42: x += 1', '', 'exec')
Or do you just assume 'exec'?
We could define it as trying the three in order (first 'eval', then 'single', then 'exec') moving on to the next option if it raises syntax error:
from dis import dis def dis_str(source): modes = ('eval', 'single', 'exec') for mode in modes: try: c = compile(source, '', mode) break except SyntaxError: if mode is modes[-1]: raise return dis(c)
Allowing 'single' has five unfortunate side effects: first, newlines at the end make a difference; second, there will be PRINT_EXPRs sprinkled in the disassembly seemingly coming from nowhere, third, statements after the first will disappear:
dis_str("for x in range(10): x\n") 1 0 SETUP_LOOP 24 (to 27) 3 LOAD_NAME 0 (range) 6 LOAD_CONST 0 (10) 9 CALL_FUNCTION 1 12 GET_ITER >> 13 FOR_ITER 10 (to 26) 16 STORE_NAME 1 (x) 19 LOAD_NAME 1 (x) 22 PRINT_EXPR 23 JUMP_ABSOLUTE 13 >> 26 POP_BLOCK >> 27 LOAD_CONST 1 (None) 30 RETURN_VALUE
dis_str("for x in range(10): x") 1 0 SETUP_LOOP 24 (to 27) 3 LOAD_NAME 0 (range) 6 LOAD_CONST 0 (10) 9 CALL_FUNCTION 1 12 GET_ITER >> 13 FOR_ITER 10 (to 26) 16 STORE_NAME 1 (x) 19 LOAD_NAME 1 (x) 22 POP_TOP 23 JUMP_ABSOLUTE 13 >> 26 POP_BLOCK >> 27 LOAD_CONST 1 (None) 30 RETURN_VALUE
dis_str("x=1\nx=2\n") 1 0 LOAD_CONST 0 (1) 3 STORE_NAME 0 (x) 6 LOAD_CONST 1 (None) 9 RETURN_VALUE
I don't think using "single" makes sense here; trying "eval" can't hurt, though. Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out.
![](https://secure.gravatar.com/avatar/f3ba3ecffd20251d73749afbfa636786.jpg?s=120&d=mm&r=g)
Georg Brandl wrote:
I don't think using "single" makes sense here; trying "eval" can't hurt, though.
Agreed. Only having the two modes to worry about greatly simplifies the code as well: from dis import dis def dis_str(source): try: c = compile(source, '', 'eval') except SyntaxError: c = compile(source, '', 'exec') return dis(c) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
participants (4)
-
Georg Brandl
-
Nick Coghlan
-
Steven D'Aprano
-
Terry Reedy