Search code examples
pythontkinterturtle-graphics

Python 3.x turtles extremely slow?


I've found that python's turtle implementation is amazingly slow. I expected some delay, but not minutes of waiting for a relatively simple fractal (Koch curve with 5 iterations).

Even after setting turtle.speed(0) it is still very slow. Maybe there's a bug since it's not instantaneous like claimed in the docs?

This answer suggested re-implementing turtles by hiding a window. A similar question got no answer. Am I missing something, or is re-implementing the way to go?

Here is my stripped down code (the creation of the l-system is almost instantaneous):

import turtle

def l_system(V, w, P, n):
    current = w

    for i in range(n):
        current = [P[x] if x in P else x for x in list(current)]
        current = ''.join(current)

    return current

def run_turtle(var, start, rules, iters, angle, size, scale):
    terry = turtle.Turtle()
    terry.pensize(1)
    terry.pencolor("blue")
    terry.speed(0)

    dist = size / ((iters + 1) ** scale)
    positions = []
    angles = []

    instructions = l_system(var, start, rules, iters)

    for instr in instructions:
        if instr in ('F', 'G'):
            terry.forward(dist)

        elif instr in ('M', 'N'):
            terry.penup()
            terry.forward(dist)
            terry.pendown()

        elif instr == '[':
            positions.append(terry.pos())
            angles.append(terry.heading())

        elif instr == ']':
            terry.goto(positions.pop())
            terry.setheading(angles.pop())

        elif instr == '+':
            terry.left(angle)

        elif instr == '-':
            terry.right(angle)

    turtle.mainloop()

def right_koch():
    run_turtle(('F',), 'F', {'F':'F+F-F-F+F'}, 5, 90, 500, 3)

right_koch()

Solution

  • Turn off the drawing delay:

    turtle.delay(0)
    

    and hide the turtle:

    terry.ht()
    

    Turning off the drawing delay is the big one. If you don't do that, there's a 10-millisecond pause whenever the turtle moves.


    If you want it to go even faster, and you only care about the finished picture, you can turn off screen updates entirely:

    turtle.tracer(0, 0)
    

    and call update a single time when your turtle has executed all its commands:

    terry.update()
    

    With tracing off and a manual update call, the program finishes near-instantaneously on my machine.