Lazy Loading
Lazy Loading
PraisonAI PPT uses lazy loading for optional dependencies, ensuring the core package works without requiring all optional features to be installed.
What is Lazy Loading?
Lazy loading is a design pattern that delays the import of optional dependencies until they are actually needed. This provides several benefits:
- Smaller Installation: Core package has minimal dependencies
- Faster Startup: Only load what you need
- No Import Errors: Package works even without optional dependencies
- Clear Feedback: Helpful error messages when features are unavailable
How It Works
Traditional Import (Eager Loading)
# This fails if google-api-python-client is not installed
from googleapiclient.discovery import build
def upload_file():
service = build('drive', 'v3')
# ... upload logic
Lazy Loading
from praisonaippt.lazy_loader import lazy_import
# This doesn't fail - import happens only when accessed
google_api = lazy_import('googleapiclient.discovery', 'Google Drive upload', 'gdrive')
def upload_file():
# Import happens here, only if function is called
service = google_api.build('drive', 'v3')
# ... upload logic
Using Lazy Loading in Your Code
Basic Usage
from praisonaippt.lazy_loader import lazy_import
# Create a lazy loader
service_account = lazy_import(
'google.oauth2.service_account', # Module to import
'Google Drive upload', # Feature name (for error messages)
'gdrive' # pip install extra name
)
# Module is not imported yet - no error even if not installed
# Use it like a normal module
credentials = service_account.Credentials.from_service_account_file('key.json')
# Module is imported here, only when accessed
Check Availability Before Use
from praisonaippt.lazy_loader import check_optional_dependency
if check_optional_dependency('google.oauth2.service_account'):
# Dependencies are available
from praisonaippt.gdrive_uploader import upload_to_gdrive
result = upload_to_gdrive('file.pptx', credentials_path='creds.json')
else:
# Dependencies not available
print("Install with: pip install praisonaippt[gdrive]")
Error Handling
from praisonaippt.lazy_loader import lazy_import, LazyImportError
try:
google_api = lazy_import('googleapiclient.discovery', 'Google Drive', 'gdrive')
service = google_api.build('drive', 'v3')
except LazyImportError as e:
print(f"Feature not available: {e.feature_name}")
print(f"Install with: pip install praisonaippt[{e.install_extra}]")
Features Using Lazy Loading
Google Drive Upload
The Google Drive upload feature uses lazy loading:
# This works even without Google Drive dependencies installed
from praisonaippt import create_presentation
data = {"presentation_title": "Test", "sections": []}
output = create_presentation(data)
# This only loads Google Drive dependencies when called
from praisonaippt.gdrive_uploader import is_gdrive_available
if is_gdrive_available():
from praisonaippt.gdrive_uploader import upload_to_gdrive
upload_to_gdrive(output, credentials_path='creds.json')
PDF Conversion (Aspose)
PDF conversion with Aspose also uses optional dependencies:
# Install without Aspose
pip install praisonaippt
# Aspose is loaded only when using --convert-pdf with --pdf-backend aspose
praisonaippt -i verses.json --convert-pdf --pdf-backend aspose
API Reference
lazy_import(module_name, feature_name, install_extra)
Create a lazy loader for an optional module.
Parameters:
module_name(str): Name of the module to import (e.g., ‘google.oauth2.service_account’)feature_name(str): Human-readable feature name (e.g., ‘Google Drive upload’)install_extra(str): Extra name for pip install (e.g., ‘gdrive’)
Returns:
LazyLoader: Lazy loader instance
Example:
google_auth = lazy_import('google.oauth2.service_account', 'Google Drive', 'gdrive')
credentials = google_auth.Credentials.from_service_account_file('key.json')
check_optional_dependency(module_name)
Check if an optional dependency is available without importing it.
Parameters:
module_name(str): Name of the module to check
Returns:
bool: True if module is available, False otherwise
Example:
if check_optional_dependency('google.oauth2.service_account'):
print("Google Drive upload is available")
else:
print("Install with: pip install praisonaippt[gdrive]")
LazyImportError
Custom exception raised when a lazy import fails.
Attributes:
module_name(str): Name of the missing modulefeature_name(str): Human-readable feature nameinstall_extra(str): Extra name for pip install
Example:
from praisonaippt.lazy_loader import LazyImportError
try:
# ... code using lazy import
except LazyImportError as e:
print(f"Missing: {e.module_name}")
print(f"For: {e.feature_name}")
print(f"Install: pip install praisonaippt[{e.install_extra}]")
Creating Your Own Lazy Loaded Features
Step 1: Create the Lazy Loader
from praisonaippt.lazy_loader import lazy_import
# In your module
my_optional_lib = lazy_import(
'optional_library',
'My Feature',
'myfeature'
)
def my_function():
# Library is imported only when this function is called
result = my_optional_lib.do_something()
return result
Step 2: Add to setup.py
extras_require={
'myfeature': ['optional-library>=1.0.0'],
'all': ['optional-library>=1.0.0', ...],
}
Step 3: Provide Availability Check
from praisonaippt.lazy_loader import check_optional_dependency
def is_myfeature_available():
return check_optional_dependency('optional_library')
Step 4: Document Usage
"""
To use this feature, install with:
pip install praisonaippt[myfeature]
Or check availability:
from mymodule import is_myfeature_available
if is_myfeature_available():
# Use feature
"""
Best Practices
1. Always Provide Availability Checks
def is_feature_available():
return check_optional_dependency('required_module')
2. Use Descriptive Feature Names
# Good
lazy_import('google.oauth2', 'Google Drive upload', 'gdrive')
# Bad
lazy_import('google.oauth2', 'feature', 'extra')
3. Handle Errors Gracefully
try:
from .optional_feature import do_something
result = do_something()
except LazyImportError:
print("Feature not available. Install with: pip install package[extra]")
result = None
4. Document Requirements Clearly
Always document:
- What the feature does
- How to install dependencies
- How to check availability
- Example usage
5. Test Without Dependencies
Ensure your package works without optional dependencies:
# Test in clean environment
python -m venv test_env
source test_env/bin/activate
pip install praisonaippt # Without extras
python -c "from praisonaippt import create_presentation; print('OK')"
Installation Extras
PraisonAI PPT provides several installation extras:
# Core package only
pip install praisonaippt
# With PDF conversion (Aspose)
pip install praisonaippt[pdf-aspose]
# With PDF conversion (all backends)
pip install praisonaippt[pdf-all]
# With Google Drive upload
pip install praisonaippt[gdrive]
# With everything
pip install praisonaippt[all]
Troubleshooting
Import Errors
Problem: Getting import errors even with lazy loading
Solution: Make sure you’re not importing the module at the top level:
# Wrong - imports immediately
from googleapiclient.discovery import build
# Correct - imports lazily
from praisonaippt.lazy_loader import lazy_import
google_api = lazy_import('googleapiclient.discovery', 'Feature', 'extra')
Feature Not Available
Problem: Feature shows as not available even after installing
Solution: Restart Python interpreter or reinstall:
pip uninstall praisonaippt
pip install praisonaippt[gdrive]
Confusing Error Messages
Problem: Error messages don’t clearly indicate what’s missing
Solution: Always use descriptive feature names and install extras:
lazy_import(
'module.name',
'Clear Feature Description', # Shows in error message
'install-extra' # Shows in pip install command
)
Performance Considerations
Startup Time
Lazy loading improves startup time by deferring imports:
# Without lazy loading
import time
start = time.time()
from googleapiclient.discovery import build # ~0.5s
from google.oauth2.service_account import Credentials # ~0.3s
print(f"Import time: {time.time() - start}s") # ~0.8s
# With lazy loading
start = time.time()
from praisonaippt.lazy_loader import lazy_import
google_api = lazy_import('googleapiclient.discovery', 'GDrive', 'gdrive')
print(f"Import time: {time.time() - start}s") # ~0.001s
Memory Usage
Lazy loading reduces memory usage for unused features:
# Memory is only allocated when feature is used
from praisonaippt import create_presentation
# Low memory usage - Google Drive not loaded
data = {"presentation_title": "Test", "sections": []}
create_presentation(data)
# Memory increases only if Google Drive is used
from praisonaippt.gdrive_uploader import upload_to_gdrive
upload_to_gdrive('file.pptx', credentials_path='creds.json')
Examples
Example 1: Optional Feature with Fallback
from praisonaippt.lazy_loader import check_optional_dependency
def save_presentation(data, output_file, upload=False):
from praisonaippt import create_presentation
# Create presentation
result = create_presentation(data, output_file)
# Upload if requested and available
if upload:
if check_optional_dependency('google.oauth2.service_account'):
from praisonaippt.gdrive_uploader import upload_to_gdrive
upload_to_gdrive(result, credentials_path='creds.json')
print("Uploaded to Google Drive")
else:
print("Google Drive upload not available")
print("Install with: pip install praisonaippt[gdrive]")
return result
Example 2: Multiple Optional Features
from praisonaippt.lazy_loader import check_optional_dependency
def process_presentation(data, options):
from praisonaippt import create_presentation
# Create presentation
output = create_presentation(data)
# Optional: Convert to PDF
if options.get('pdf') and check_optional_dependency('aspose.slides'):
from praisonaippt import convert_pptx_to_pdf
convert_pptx_to_pdf(output)
# Optional: Upload to Google Drive
if options.get('upload') and check_optional_dependency('google.oauth2'):
from praisonaippt.gdrive_uploader import upload_to_gdrive
upload_to_gdrive(output, credentials_path='creds.json')
return output
Example 3: Graceful Degradation
from praisonaippt.lazy_loader import lazy_import, LazyImportError
def upload_with_fallback(file_path):
try:
# Try Google Drive first
from praisonaippt.gdrive_uploader import upload_to_gdrive
result = upload_to_gdrive(file_path, credentials_path='creds.json')
return f"Uploaded to Google Drive: {result['webViewLink']}"
except LazyImportError:
# Fall back to local storage
print("Google Drive not available, keeping file locally")
return f"Saved locally: {file_path}"
except Exception as e:
print(f"Upload failed: {e}")
return f"Saved locally: {file_path}"