Python library for importing Wavefront .obj files and generating interleaved vertex data ready for rendering.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Logging configuration, exception handling, and utility functions for customizing PyWavefront behavior and debugging.
PyWavefront provides configurable logging for debugging and monitoring parsing operations.
def configure_logging(level, formatter=None) -> None:
"""
Configure PyWavefront's logging system.
Parameters:
- level: Logging level (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR)
- formatter: Optional logging.Formatter instance for custom formatting
Default behavior:
- Logger name: "pywavefront"
- Default level: ERROR
- Default handler: StreamHandler (console output)
"""Default Logging Configuration:
"pywavefront"ERROR (only errors shown)StreamHandlerclass PywavefrontException(Exception):
"""
Custom exception class for PyWavefront-specific errors.
Raised for:
- File parsing errors
- Missing material references
- Unsupported .obj features in strict mode
- File access issues
- Malformed geometry data
"""Common Exception Scenarios:
create_materials=Falseusemtl statementsstrict=True__version__: str # Current version stringimport pywavefront
print(pywavefront.__version__) # "1.3.3"import logging
import pywavefront
# Enable debug logging for detailed parsing information
pywavefront.configure_logging(logging.DEBUG)
# Load a file with debug output
scene = pywavefront.Wavefront('model.obj')
# Output: Debug information about parsing progress, timing, etc.import logging
import pywavefront
# Create a custom formatter
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Configure with custom formatter
pywavefront.configure_logging(logging.INFO, formatter=formatter)
# Load with timestamped logging
scene = pywavefront.Wavefront('model.obj')import logging
import pywavefront
# Different logging levels show different information:
# ERROR (default): Only critical errors
pywavefront.configure_logging(logging.ERROR)
# WARNING: Warnings about potential issues
pywavefront.configure_logging(logging.WARNING)
# INFO: General information about parsing progress
pywavefront.configure_logging(logging.INFO)
# DEBUG: Detailed parsing information and timing
pywavefront.configure_logging(logging.DEBUG)import pywavefront
try:
# Strict parsing that raises exceptions for unsupported features
scene = pywavefront.Wavefront('model.obj', strict=True)
except pywavefront.PywavefrontException as e:
print(f"PyWavefront error: {e}")
# Handle PyWavefront-specific errors
except FileNotFoundError as e:
print(f"File not found: {e}")
# Handle file access errors
except Exception as e:
print(f"Unexpected error: {e}")
# Handle other unexpected errors
# Graceful handling of missing materials
try:
scene = pywavefront.Wavefront('model_with_missing_mtl.obj')
except pywavefront.PywavefrontException:
print("Missing materials detected, creating defaults...")
scene = pywavefront.Wavefront('model_with_missing_mtl.obj', create_materials=True)import logging
import pywavefront
# Enable debug logging to troubleshoot loading issues
pywavefront.configure_logging(logging.DEBUG)
try:
# Load with maximum debugging information
scene = pywavefront.Wavefront(
'problematic_model.obj',
strict=True, # Catch parsing issues
encoding='utf-8' # Ensure correct encoding
)
print(f"Successfully loaded {len(scene.materials)} materials")
print(f"Found {len(scene.mesh_list)} meshes")
except pywavefront.PywavefrontException as e:
print(f"Parsing failed: {e}")
# Try with relaxed settings
print("Retrying with relaxed parsing...")
scene = pywavefront.Wavefront(
'problematic_model.obj',
strict=False,
create_materials=True
)import time
import logging
import pywavefront
# Configure INFO level to see load timing
pywavefront.configure_logging(logging.INFO)
start_time = time.time()
# Load with caching for performance
scene = pywavefront.Wavefront('large_model.obj', cache=True)
load_time = time.time() - start_time
print(f"Load completed in {load_time:.2f} seconds")
# Subsequent loads will be much faster due to caching
start_time = time.time()
scene2 = pywavefront.Wavefront('large_model.obj', cache=True)
cached_load_time = time.time() - start_time
print(f"Cached load completed in {cached_load_time:.2f} seconds")
print(f"Speedup: {load_time / cached_load_time:.1f}x")import pywavefront
def load_model_robust(filepath):
"""Robust model loading with multiple fallback strategies."""
# Strategy 1: Normal loading
try:
return pywavefront.Wavefront(filepath)
except pywavefront.PywavefrontException:
pass
# Strategy 2: Create missing materials
try:
return pywavefront.Wavefront(filepath, create_materials=True)
except pywavefront.PywavefrontException:
pass
# Strategy 3: Disable strict parsing
try:
return pywavefront.Wavefront(
filepath,
strict=False,
create_materials=True
)
except pywavefront.PywavefrontException:
pass
# Strategy 4: Try different encoding
try:
return pywavefront.Wavefront(
filepath,
encoding='latin1',
strict=False,
create_materials=True
)
except Exception as e:
raise pywavefront.PywavefrontException(
f"Failed to load {filepath} with all strategies: {e}"
)
# Usage
try:
scene = load_model_robust('difficult_model.obj')
print("Model loaded successfully")
except pywavefront.PywavefrontException as e:
print(f"All loading strategies failed: {e}")DEBUG Level Output:
pywavefront: Load time: 0.123
pywavefront: Parsing vertex data: 1000 vertices
pywavefront: Loading material library: materials.mtl
pywavefront: Created material: wood_material
pywavefront: Face parsing complete: 500 triangular facesINFO Level Output:
pywavefront: model.obj: Load time: 0.123WARNING Level Output:
pywavefront: Unknown material reference: missing_material
pywavefront: Creating default material: default0ERROR Level Output:
pywavefront: Failed to load material library: materials.mtl
pywavefront: PywavefrontException: Unknown material: metal_surfaceInstall with Tessl CLI
npx tessl i tessl/pypi-pywavefront