ifcos-syntax-fileio
IfcOpenShell File I/O Operations
Quick Reference
Decision Tree: Opening vs Creating IFC Files
Need an IFC model?
├── Existing file on disk?
│ └── YES → ifcopenshell.open("path/to/file.ifc")
│ ├── Large file (100MB+)? → use should_stream=True
│ └── Non-standard extension? → use format=".ifc"
│
└── NO → Create new file
├── Need header metadata, timestamps, MVD? (production use)
│ └── YES → ifcopenshell.api.project.create_file(version="IFC4")
│
└── Need bare-minimum empty file? (testing, prototyping)
└── ifcopenshell.file(schema="IFC4")
Decision Tree: Writing Output
Need to output IFC data?
├── Write to disk?
│ ├── Standard .ifc → model.write("output.ifc")
│ ├── XML format → model.write("output.ifcXML")
│ ├── Compressed → model.write("output.ifc", zipped=True)
│ └── ZIP archive → model.write("output.ifcZIP")
│
└── Get as string? → model.to_string()
Critical Warnings
- ALWAYS specify
schema=explicitly when callingifcopenshell.file(). The default is"IFC4"but relying on implicit defaults is error-prone. - ALWAYS check
model.schemaafter opening a file before using schema-specific entities. - NEVER use
ifcopenshell.file()for production IFC creation. Useifcopenshell.api.project.create_file()instead — it sets up header metadata, timestamps, and MVD automatically. - NEVER call
model.remove()without understanding that references to the removed entity become null. Useifcopenshell.api.run("root.remove_product", ...)for safe removal of products. - ALWAYS wrap undo-able operations in
begin_transaction()/end_transaction()pairs. NEVER leave a transaction open. - NEVER call
undo()orredo()while a transaction is active.
Essential Patterns
Pattern 1: Open an Existing IFC File
# IfcOpenShell — all schema versions
import ifcopenshell
model = ifcopenshell.open("/path/to/model.ifc")
print(model.schema) # "IFC2X3", "IFC4", or "IFC4X3"
print(f"Entities: {len(model)}")
Pattern 2: Create a New IFC File (Production)
# IfcOpenShell — IFC4 (change version= for IFC2X3 or IFC4X3)
import ifcopenshell
import ifcopenshell.api
model = ifcopenshell.api.run("project.create_file", version="IFC4")
project = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcProject", name="My Project")
ifcopenshell.api.run("unit.assign_unit", model)
context = ifcopenshell.api.run("context.add_context", model,
context_type="Model", context_identifier="Body",
target_view="MODEL_VIEW")
Pattern 3: Create a New IFC File (Bare Minimum)
# IfcOpenShell — IFC4 (specify schema= for other versions)
import ifcopenshell
model = ifcopenshell.file(schema="IFC4")
# WARNING: This file has NO header, NO project, NO units.
# ALWAYS add at minimum: IfcProject, units, and a geometric context.
Pattern 4: Write IFC to Disk
# IfcOpenShell — all schema versions
model.write("/path/to/output.ifc")
# Write as compressed ZIP
model.write("/path/to/output.ifc", zipped=True)
# Write as XML format
model.write("/path/to/output.ifcXML")
Pattern 5: Serialize IFC to String
# IfcOpenShell — all schema versions
ifc_string = model.to_string()
Pattern 6: Transaction Management (Undo/Redo)
# IfcOpenShell — all schema versions
model.begin_transaction()
wall = model.create_entity("IfcWall",
GlobalId=ifcopenshell.guid.new(), Name="Test Wall")
model.end_transaction()
# Undo the transaction
model.undo()
# Redo the transaction
model.redo()
Pattern 7: Transfer Entity Between Files
# IfcOpenShell — all schema versions
source = ifcopenshell.open("source.ifc")
target = ifcopenshell.file(schema=source.schema)
wall = source.by_type("IfcWall")[0]
target.add(wall) # Recursively adds wall and all referenced entities
target.write("target.ifc")
Pattern 8: Remove Entity from File
# IfcOpenShell — all schema versions
wall = model.by_type("IfcWall")[0]
model.remove(wall)
# WARNING: All attributes referencing this entity become null ($).
# Aggregate references (lists/sets) are cleaned up automatically.
Common Operations
Opening Files
# IfcOpenShell — all schema versions
import ifcopenshell
# Standard file open
model = ifcopenshell.open("building.ifc")
# Open ZIP-compressed IFC
model = ifcopenshell.open("building.ifcZIP")
# Open XML-format IFC
model = ifcopenshell.open("building.ifcXML")
# Force format when extension is non-standard
model = ifcopenshell.open("building.dat", format=".ifc")
# Streaming mode for large files (100MB+)
# WARNING: Only supports sequential iteration, NOT random access
model = ifcopenshell.open("huge_model.ifc", should_stream=True)
for entity in model:
if entity.is_a("IfcWall"):
print(entity.Name)
Creating Files
# IfcOpenShell — IFC4 (change version/schema for other versions)
import ifcopenshell
import ifcopenshell.api
# RECOMMENDED: Production file with proper header
model = ifcopenshell.api.run("project.create_file", version="IFC4")
# Alternative: Bare empty file (testing only)
model = ifcopenshell.file(schema="IFC4")
# IFC2X3 file
model_legacy = ifcopenshell.file(schema="IFC2X3")
# IFC4X3 file (infrastructure projects)
model_infra = ifcopenshell.file(schema="IFC4X3")
# Specific schema sub-version
model_specific = ifcopenshell.file(schema_version=(4, 0, 2, 1)) # IFC4 ADD2 TC1
Writing Files
# IfcOpenShell — all schema versions
# Standard STEP format
model.write("output.ifc")
# XML serialization
model.write("output.ifcXML")
# ZIP-compressed STEP
model.write("output.ifcZIP")
# STEP with additional ZIP compression
model.write("output.ifc", zipped=True)
# ZIP-compressed XML
model.write("output.ifcXML", format=".ifcXML", zipped=True)
# Serialize to string (no file written)
ifc_text = model.to_string()
Adding and Removing Entities
# IfcOpenShell — all schema versions
import ifcopenshell
# Add entity from another file (copies entity + all dependencies)
source = ifcopenshell.open("source.ifc")
target = ifcopenshell.file(schema=source.schema)
wall = source.by_type("IfcWall")[0]
target.add(wall)
# Remove entity from file
model.remove(wall)
Transaction Management
# IfcOpenShell — all schema versions
# Basic transaction
model.begin_transaction()
wall = model.create_entity("IfcWall",
GlobalId=ifcopenshell.guid.new(), Name="New Wall")
model.end_transaction()
# Undo last transaction
model.undo()
# Redo undone transaction
model.redo()
# Discard transaction without recording
model.begin_transaction()
# ... experimental changes ...
model.discard_transaction()
# Set maximum undo history size (default: 64)
model.set_history_size(128)
Error Handling
# IfcOpenShell — all schema versions
import ifcopenshell
try:
model = ifcopenshell.open("model.ifc")
except FileNotFoundError:
print("File not found")
except ifcopenshell.Error:
print("Invalid or corrupt IFC file")
Accessing File Metadata
# IfcOpenShell — all schema versions
model = ifcopenshell.open("model.ifc")
# Schema information
print(model.schema) # "IFC2X3", "IFC4", or "IFC4X3"
print(model.schema_identifier) # e.g., "IFC4_ADD2"
print(model.schema_version) # e.g., (4, 0, 2, 1)
# Header information
print(model.header.file_description)
print(model.header.file_name)
print(model.header.file_schema)
# Entity count
print(len(model))
Version Notes
Schema Parameter Differences
| Method | Parameter | Values |
|---|---|---|
ifcopenshell.file() |
schema= |
"IFC2X3", "IFC4", "IFC4X3" |
ifcopenshell.api.project.create_file() |
version= |
"IFC2X3", "IFC4", "IFC4X3" |
ALWAYS use the correct parameter name: schema= for file(), version= for create_file().
ifcopenshell.file() vs ifcopenshell.api.project.create_file()
| Feature | ifcopenshell.file() |
api.project.create_file() |
|---|---|---|
| Header metadata | Empty/minimal | Pre-populated (timestamp, app info) |
| Preprocessor | Not set | Set to "IfcOpenShell" |
| MVD | Not set | DesignTransferView default |
| Timestamp | Not set | Current timestamp |
| Use case | Testing, prototyping | Production IFC creation |
Reference Links
- API Method Signatures — Complete signatures for all file I/O methods
- Working Code Examples — End-to-end examples for all file operations
- Anti-Patterns — Common file I/O mistakes and how to avoid them
More from openaec-foundation/computational-design-day-delft-march-2026
blender-core-api
Guides Blender Python API usage including bpy module structure, RNA data access, context system, dependency graph, and operator invocation. Activates when writing bpy scripts, creating Blender addons, or accessing Blender data blocks programmatically.
1blender-syntax-panels
Defines Blender UI panel creation including bpy.types.Panel, draw() method, UILayout API (row/column/box/split), bl_space_type, bl_region_type, bl_category, sub-panels, draw_header, menus, and UIList. Activates when creating custom Blender panels, building addon interfaces, or working with UILayout elements.
1ifcos-syntax-api
Documents the ifcopenshell.api module system with all 30+ API modules, invocation patterns via api.run() and direct module calls, parameter conventions, and module categorization. Activates when creating IFC entities, modifying properties, managing spatial structure, or using any ifcopenshell.api function.
1bonsai-impl-bcf
Guides implementation of BIM Collaboration Format (BCF) workflows in Bonsai including creating BCF topics, adding viewpoints with camera snapshots, managing comments, importing/exporting BCF files (v2.1 and v3.0), and integrating BCF issue tracking with IFC element references. Activates when working with BCF files, BIM issue tracking, clash report management, or collaboration workflows in Bonsai.
1ifcos-impl-mep
Guides MEP (Mechanical, Electrical, Plumbing) modeling in IFC using ifcopenshell.api.system including IfcSystem, IfcDistributionElement, ports, connections, flow segments, fittings, and MEP-specific property sets. Activates when creating HVAC systems, piping networks, electrical circuits, or MEP elements in IFC models.
1ifcos-impl-cost
Guides IFC cost management using ifcopenshell.api.cost including cost schedules, cost items, cost values, cost quantities, and 5D BIM workflows. Activates when implementing cost estimation in IFC models, creating cost schedules, or linking quantities to cost items.
1