Skip to content
BIMpedia
Chapter 2 · Lesson 2 of 3Topic: Scripting and APIs

Reading IFC with Python

A few lines of Python with IfcOpenShell open any IFC file, find elements, read their properties and write a report, without any authoring software.

3 min read3 quiz questions
Skip to the quiz
  • Watch out
  • What it costs
  • Experienced readers
  • Remember
  • In BIMpedia
Adadata and automation lead
Even if you do this every day, watch for this: Where the properties are. Scripts written against Pset_DoorCommon miss everything a vendor exported into its own sets; read both, then fix the export.

IFC is an open format, and open-source libraries can read it. With IfcOpenShell (Python), a short script can open any IFC file, from any authoring tool, and answer questions about it: counts, missing properties, lists for a report. It runs on a laptop, a server or a notebook, without Revit, Archicad or a licence.

The minimum you need to know

IFC ideaExampleIn Python
Entities (classes)IfcDoor, IfcWall, IfcSpacemodel.by_type("IfcDoor")
Property setsPset_DoorCommon.FireRatingget_psets(door)["Pset_DoorCommon"]["FireRating"]
ContainmentThe storey that contains the doorget_container(door).Name
TypesThe door type an instance usesget_type(door)
GlobalIdA stable ID per elementdoor.GlobalId
Basics

IfcOpenShell installs with pip install ifcopenshell. A script opens a file with ifcopenshell.open("model.ifc"), gets elements with by_type, and reads data with the helpers in ifcopenshell.util.element.

A useful first script

List every space with its storey, number and area, and flag spaces with no number:

import ifcopenshell
import ifcopenshell.util.element as el

model = ifcopenshell.open("model.ifc")
for space in model.by_type("IfcSpace"):
    psets = el.get_psets(space)
    qtos = psets.get("Qto_SpaceBaseQuantities", {})
    storey = el.get_container(space)
    number = space.Name or ""            # many exporters store the room number here
    area = qtos.get("NetFloorArea")
    flag = "" if number else "  <-- no number"
    print(f"{storey.Name if storey else '-':10} {number:10} {space.LongName or '':25} {area or '-'}{flag}")
Adadata and automation lead
Your turn. Give it about 15 min and work it out on your own before you open the model answer: that is where it sticks.
Exercise: Read the script 15 min

Read this script, then answer the questions:

import ifcopenshell
import ifcopenshell.util.element as el
from collections import Counter

model = ifcopenshell.open("model.ifc")
missing = Counter()
for wall in model.by_type("IfcWall"):
    ext = el.get_psets(wall).get("Pset_WallCommon", {}).get("IsExternal")
    if ext is None:
        storey = el.get_container(wall)
        missing[storey.Name if storey else "no storey"] += 1
for storey, n in missing.most_common():
    print(storey, n)
  1. What does it report?
  2. A wall has IsExternal = False. Is it counted?
  3. How would you change it to also list the GlobalIds of the walls?

Key takeaways

  • IfcOpenShell opens IFC files from any software; scripts work across vendors.
  • Find elements by class (IfcDoor, IfcSpace), then read property sets and the containing storey.
  • Expect properties in custom sets as well as standard ones; check both.
  • Skip geometry when you only need data: it's much faster.

Your notes

Related tool

Open an IFC file in the browser: structure, elements, properties and required-property checks.

Open IFC Inspector →

Check yourself

3 questions · 2 right to complete
  1. 1. What does model.by_type('IfcSpace') return?
  2. 2. A script finds no FireRating on doors that clearly have one in the authoring tool. Why might that be?
  3. 3. Why run property checks without loading geometry?
0 of 3 answered