Hello, world!

If you’re reading this, we assume you already know IFC and just want to quickly get started with IfcOpenShell.

This crash course guides you through basic code snippets that give you a general idea of the low-level functionality that IfcOpenShell-python provides. You’ll need to have IfcOpenShell installed and a sample IFC model. To get the most out of it, try out the code yourself and see what results you get!

If you don’t have an IFC model available, here’s a small one for your convenience provided by the Institute for Automation and Applied Informatics (IAI) / Karlsruhe Institute of Technology. It’s in German, so you may need to use some creativity when reading the data :)

See also

You can find more sample models online in the OSArch Open Data Directory

Let’s start with loading the model. Import the IfcOpenShell module, then use the open function to load the model into a variable called model.

import ifcopenshell
model = ifcopenshell.open('/path/to/your/model.ifc')

Let’s see what IFC schema we are using:

print(model.schema) # May return IFC2X3, IFC4, or IFC4X3.

Let’s get the first piece of data in our IFC file:


But getting data from beginning to end isn’t too meaningful to humans. What if we knew a GlobalId value instead?


If we’re not looking specifically for a single element, perhaps let’s see how many walls are in our file, and count them:

walls = model.by_type('IfcWall')

Once we have an element, we can see what IFC class it is:

wall = model.by_type('IfcWall')[0]
print(wall.is_a()) # Returns 'IfcWall'

You can also test if it is a certain class, as well as check for parent classes too:

print(wall.is_a('IfcWall')) # Returns True
print(wall.is_a('IfcElement')) # Returns True
print(wall.is_a('IfcWindow')) # Returns False

Let’s quickly check the STEP ID of our element:


Let’s get some attributes of an element. IFC attributes have a particular order. We can access it just like a list, so let’s get the first and third attribute:

print(wall[0]) # The first attribute is the GlobalId
print(wall[2]) # The third attribute is the Name

Knowing the order of attributes is boring and technical. We can access them by name too:


Getting attributes one by one is tedious. Let’s grab them all:

# Gives us a dictionary of attributes, such as:
# {'id': 8, 'type': 'IfcWall', 'GlobalId': '2_qMTAIHrEYu0vYcqK8cBX', ... }

Let’s see all the properties and quantities associated with this wall:

import ifcopenshell.util
import ifcopenshell.util.element

Some attributes are special, called “inverse attributes”. They happen when another element is referencing our element. They can reference it for many reasons, like to define a relationship, such as if they create a void in our wall, join our wall, or define a quantity take-off value for our wall, among others. Just treat them like regular attributes:


Perhaps we want to see all elements which are referencing our wall?


Let’s do the opposite, let’s see all the elements which our wall references instead:

# Or, let's just go down one level deep
print(model.traverse(wall, max_levels=1))

If you want to modify data, just assign it to the relevant attribute:

wall.Name = 'My new wall name'

You can also generate a new GlobalId:

wall.GlobalId = ifcopenshell.guid.new()

After modifying some IFC data, you can save it to a new IFC-SPF file:


You can generate a new IFC from scratch too, instead of reading an existing one:

ifc = ifcopenshell.file()
# Or if you want a particular schema:
ifc = ifcopenshell.file(schema='IFC4')

You can create new IFC elements, and add it either to an existing or newly created IFC file object:

# Will return #1=IfcWall($,$,$,$,$,$,$,$,$) - notice all of the attributes are blank!
new_wall = model.createIfcWall()
# Will return a list with our wall in it: [#1=IfcWall($,$,$,$,$,$,$,$,$)]

Alternatively, you can also use this way to create new elements:


Specifying more arguments lets you fill in attributes while creating the element instead of assigning them separately. You specify them in the order of the attributes.

# Gives us #1=IfcWall('0EI0MSHbX9gg8Fxwar7lL8',$,$,$,$,$,$,$,$)
model.create_entity('IfcWall', ifcopenshell.guid.new())

Again, knowing the order of attributes is difficult, so you can use keyword arguments instead:

# Gives us #1=IfcWall('0EI0MSHbX9gg8Fxwar7lL8',$,'Wall Name',$,$,$,$,$,$)
model.create_entity('IfcWall', GlobalId=ifcopenshell.guid.new(), Name='Wall Name')

Sometimes, it’s easier to expand a dictionary:

data = {
    'GlobalId': ifcopenshell.guid.new(),
    'Name': 'Wall Name'
model.create_entity('IfcWall', **data)

Some attributes of an element aren’t just text, they may be a reference to another element. Easy:

wall = model.createIfcWall()
wall.OwnerHistory = model.createIfcOwnerHistory()

What if we already have an element from one IFC file and want to add it to another?

wall = model.by_type('IfcWall')[0]
new_model = ifcopenshell.file()

Fed up with an object? Let’s delete it:


This is only a small sample of the basic building blocks of manipulating IFC data. IFC comes with a huge utility library and API for performing common tasks. See Code examples for more.