I must use goto
in Python. I found entrians goto
but my Python implementation (CPython 2.7.1 on Mac) does not have this module, so it doesn't seem to be portable. It should at least work in all Python implementations which support CPython bytecode (esp. I care about CPython and PyPy). Then there is this related question, and cdjc's goto
. And the ones given by answers below.
I could go and build up the bytecode manually (i.e. write my own Python compiler) because there is such an instruction (JUMP_ABSOLUTE
and friends). But I wonder if there is an easier way. Is it possible via inspect
or so to call a single bytecode instruction? I also thought about compiling via Python and then automatically patching the generated Python bytecode.
Of course, people will ask why and will not give me any helpful answer if I don't explain why I really really need this. So in short my use case: I am translating a C AST to Python AST and compiling this. I can map every logical flow (all the loops and other stuff) in some way to equivalent Python code. Everything except goto
. Related projects: PyCParser (see interpreter.py
), PyCPython, PyLua.
I know what everybody is thinking:
However, there might be some didactic cases where you actually need a goto
.
This python recipe provides the goto
command as a function decorator.
The goto decorator (Python recipe by Carl Cerecke)
This is the recipe for you if you are sick of the slow speed of the existing
goto
module http://entrian.com/goto/. Thegoto
in this recipe is about 60x faster and is also cleaner (abusingsys.settrace
seems hardly pythonic). Because this is a decorator, it alerts the reader which functions usegoto
. It does not implement the comefrom command, although it is not difficult to extend it to do so (exercise for the reader). Also, computed gotos aren't supported; they're not pythonic.
- Use
dis.dis(fn)
to show the bytecode disassembly of a function.- The bytecodes of a function are accessed by
fn.func_code.co_code
. This is readonly so:- The decorated function is created exactly the same as the old one, but with the bytecode updated to obey the
goto
commands.- This is 2.x only; the new module is not in python 3.x (another exercise for the reader!)
Usage
@goto
def test1(n):
s = 0
label .myLoop
if n <= 0:
return s
s += n
n -= 1
goto .myLoop
>>> test1(10)
55
Update
Here're two additional implementations compatible with Python 3: