Why does Blender crash when trying to place objects with 'threading.Timer()'? I'm trying to make a simple program where 15 spheres are randomly placed into a 20x20x20 volume, then after two seconds it clears all the spheres and places another 15 randomly. 

It will place the first 15 spheres fine after two seconds, then after another two seconds blender closes.

Any help with this is much appreciated.

import bpy
import random
import threading

def place():

    bpy.ops.object.select_all(action='SELECT')
    bpy.ops.object.delete(use_global=False)

    for i in range(0,15):
        x = random.randint(-10,10)
        y = random.randint(-10,10)
        z = random.randint(-10,10)
        bpy.ops.mesh.primitive_uv_sphere_add(location=(x,y,z))

        bpy.ops.object.modifier_add(type='SUBSURF')
        bpy.context.object.modifiers['Subdivision'].render_levels=0
        bpy.context.object.modifiers['Subdivision'].levels=0

        timer = threading.Timer(2.0, place)
        timer.start()

    return None

place()
If I understand the code correctly, each place() method then recursively calls 15 more place() after 2 seconds, which each of these instances themselves call place() 15 more times after 2 seconds. etc. I think this will crash any program in python pretty quickly. 

Blender has specialized methods for recurrent calling of methods. See the documentation :
https://docs.blender.org/api/current/bpy.app.timers.html

Exemple :

import bpy


def every_2_seconds():
    print("Hello World")
    return 2.0


bpy.app.timers.register(every_2_seconds)