Code that ought to run fast, but can't due to Python limitations.

Hendrik van Rooyen mail at microcorp.co.za
Sun Jul 5 04:12:54 EDT 2009


"John Nagle" <nagle at ...ats.com> wrote:

> Python doesn't have a "switch" or "case" statement, and when
> you need a state machine with many states, that makes for painful,
> slow code.  There's a comment in the code that it would be useful
> to run a few billion lines of HTML through an instrumented version
> of the parser to decide in which order the IF statements should be
> executed.  You shouldn't have to do that.

You do not have to implement a state machine in a case statement,
or in a series of if... elifs.

Python is not C.

Use a dispatch dict, and have each state return the next state.
Then you can use strings representing state names, and
everybody will be able to understand the code.

toy example, not tested, nor completed:

protocol = {"start":initialiser,"hunt":hunter,"classify":classifier,....other
states}

def state_machine():
    next_step = protocol["start"]()
    while True:
        next_step = protocol[next_step]()

Simple, and almost as fast as if you did the same thing
in assembler using pointers.

And each state will have a finite set of reasons to
either stay where its at, or move on.  Not a lot you
can do about that, but test for them one at a time.
But at least you will have split the problem up,
and you won't be doing irrelevant tests.

You can even do away with the dict, by having
each state return the actual next state routine:

next_state = protocol_initialiser()
while True:
    next_state = next_state()
    time.sleep(0.001)      # this prevents thrashing when monitoring real events

If you are using a gui, and you have access
to an after callback, then you can make a
ticking stutter thread to run some monitoring
machine in the background, using the same
"tell me what to do next" technique.

To take the timing thing further, you can do:

wait_time, next_state = protocol_initialiser()
while True:
    if wait_time:
        time.sleep(wait_time)
    wait_time, next_state = next_state()

This gives you control over busy-wait loops,
and lets you speed up when it is needed.

Python really is not C.

- Hendrik







More information about the Python-list mailing list