# Scripting a boolean modifier loop, but I'm doing something wrong

I would like to make an opaque screen with many circular holes of different diameters and locations by an automated by a python script.

The locations and sizes will come from an algorithm and will appear random and some holes will overlap.

The script doesn't quite run - it gets hung up on the line indicated where I am trying to say "use this cylinder to make the hole!

The error in the console:

Traceback (most recent call last):
File "/Users/david/Documents/fishing/static concentrator/static concentrator v01.blend/Text", line 31, in <module>
TypeError: bpy_struct: item.attr = val: BooleanModifier.object ID type does not support assignment to its self
Error: Python script fail, look in the console for now...


The script:

import numpy as np
import bpy

# make a screen
screen = bpy.context.active_object
screen.scale = 0.05, 2, 2
screen.location = 0, 0, 2

cyl = bpy.context.active_object
cyl.rotation_euler = 0, 0.5*np.pi, 0
bpy.ops.object.select_all(action='DESELECT')

scales, offsets = np.array([4, 4, 0.1]), np.array([-0.5, 0, 1])

holes = (scales * (np.random.random(300).reshape(-1, 3) + offsets))

for y, z, r in holes:

cyl.location = 0, y, z
cyl.scale = r, r, 1

bpy.ops.object.select_all(action='DESELECT')
screen.select = True

# bpy.context.space_data.context = 'MODIFIER'
bpy.context.object.modifiers["Boolean"].operation = 'DIFFERENCE'
bpy.context.object.modifiers["Boolean"].object = cyl  # Hey! Use this to cut the hole please!!
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Boolean")
bpy.ops.object.select_all(action='DESELECT')


The alternate script with a tiny loop and without numpy:

import bpy
import math

# make a screen
screen = bpy.context.active_object
screen.scale = 0.05, 2, 2
screen.location = 0, 0, 2

# make a cylinder
cyl = bpy.context.active_object
cyl.rotation_euler = 0, 0.5*math.pi, 0
bpy.ops.object.select_all(action='DESELECT')

holes = [(1, 3, 0.25), (0, 2, 0.15)]

for y, z, r in holes:

cyl.location = 0, y, z
cyl.scale = r, r, 1

bpy.ops.object.select_all(action='DESELECT')
screen.select = True

# bpy.context.space_data.context = 'MODIFIER'
bpy.context.object.modifiers["Boolean"].operation = 'DIFFERENCE'
bpy.context.object.modifiers["Boolean"].object = cyl  # Hey! Use this to cut the hole please!!
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Boolean")
bpy.ops.object.select_all(action='DESELECT')


• Cutting holes is one of the harder things to do in 3d modeling programs...I would say to use a boolean modifier, but I don't know why you'd have to subdivide the plane so much... – JakeD Sep 8 '16 at 11:19
• @pycoder thanks - actually a thin slab seems to work well. I was speculating about the subdivision based on other tutorials. Actually I am making progress with my automated boolean modifier script - I am going to rewrite this question in a few minutes based on my results. Stay tuned. – uhoh Sep 8 '16 at 11:26
• @pycoder OK the question is updated - almost working script to perforate a 3D slab. No progress perforating a plane, but that's OK I can just make this thin. – uhoh Sep 8 '16 at 12:58
• try cyl.name instead of just cyl when you set the object to use. – JakeD Sep 8 '16 at 13:00
• note: This answer and it's question may contain the solution - I'll give it a try again tomorrow - if anyone wants to try first, that's great! – uhoh Sep 8 '16 at 14:49

This should work for you:

import bpy
import math

# make a screen
screen = bpy.context.active_object
screen.scale = 0.05, 2, 2
screen.location = 0, 0, 2

# make a cylinder
cyl = bpy.context.active_object
cyl.rotation_euler = 0, 0.5*math.pi, 0
bpy.ops.object.select_all(action='DESELECT')

holes = [(1, 3, 0.25), (0, 2, 0.15)]

for y, z, r in holes:

cyl.location = 0, y, z
cyl.scale = r, r, 1

bpy.ops.object.select_all(action='DESELECT')
screen.select = True  # this doesn't matter, the active object does
bpy.context.scene.objects.active = screen

# bpy.context.space_data.context = 'MODIFIER'