Python Attribute Logging Metaclass: Monitor Accesses
Python Metaprogramming: Exercise-4 with Solution
Attribute Logging Metaclass:
Write a Python metaclass “AttrLoggingMeta” that logs every time an attribute is accessed or modified.
Sample Solution:
Python Code :
# Define a metaclass AttrLoggingMeta
class AttrLoggingMeta(type):
# Override the __new__ method to log attribute accesses
def __new__(cls, name, bases, dct):
# Iterate through class attributes
for key, value in dct.items():
# Exclude special methods
if not key.startswith('__'):
# Replace attribute with a logged version
dct[key] = cls.log_access(key, value)
# Call superclass's __new__ method to create the class
return super().__new__(cls, name, bases, dct)
# Define a static method to log attribute accesses
@staticmethod
def log_access(name, value):
# If the attribute is a method, wrap it to log method calls
if callable(value):
def wrapper(*args, **kwargs):
print(f"Calling method {name}")
return value(*args, **kwargs)
return wrapper
else:
# If the attribute is a property, log read and write operations
return property(
# Log attribute read operation
fget=lambda self: AttrLoggingMeta.log_read(name, value, self),
# Log attribute write operation
fset=lambda self, v: AttrLoggingMeta.log_write(name, v, self)
)
# Define a static method to log attribute reads
@staticmethod
def log_read(name, value, instance):
print(f"Reading attribute {name}")
return value
# Define a static method to log attribute writes
@staticmethod
def log_write(name, value, instance):
print(f"Writing attribute {name} with value {value}")
# Update instance dictionary with the new value
instance.__dict__[name] = value
# Define a class LoggedClass using AttrLoggingMeta as its metaclass
class LoggedClass(metaclass=AttrLoggingMeta):
# Define a class attribute foo
foo = 42
# Define a class method bar
def bar(self):
return 'baz'
# Create an instance of LoggedClass
instance = LoggedClass()
# Access and print the value of the foo attribute
print(instance.foo) # Reading attribute foo
# Set the value of the foo attribute
instance.foo = 78 # Writing attribute foo with value 84
# Call the bar method
instance.bar() # Calling method bar
Output:
Reading attribute foo 42 Writing attribute foo with value 78 Calling method bar
Explanation:
- Metaclass AttrLoggingMeta:
- This metaclass is responsible for logging attribute accesses of classes that use it.
- The "new" method is overridden to intercept attribute assignments and replace them with logged versions.
- Inside "new", it iterates over the class attributes (excluding special methods) and replaces them with logged versions using the 'log_access' method.
- Static Method log_access:
- This method is called to replace each attribute with a logged version.
- If the attribute is a method, it wraps it with a wrapper function that logs method calls.
- If the attribute is a property, it replaces it with a property that logs read and write operations.
- Static Methods log_read and log_write:
- These methods are called to log read and write operations of properties.
- They print messages indicating the attribute name and the operation being performed.
- Class LoggedClass:
- This class is an example demonstrating the use of the "AttrLoggingMeta" metaclass.
- It contains a class attribute 'foo' and a method 'bar'.
- Instance Creation and Testing:
- An instance of 'LoggedClass' is created.
- The value of the 'foo' attribute is accessed, demonstrating logging of attribute reads.
- The value of the 'foo' attribute is changed, demonstrating logging of attribute writes.
- The "bar" method is called, demonstrating logging of method calls.
Python Code Editor :
Have another way to solve this solution? Contribute your code (and comments) through Disqus.
Previous: Python Singleton Metaclass: Ensure One Instance.
Next: Python Dynamic Class Creation: Flexibility Unleashed
What is the difficulty level of this exercise?
Test your Programming skills with w3resource's quiz.
- Weekly Trends and Language Statistics
- Weekly Trends and Language Statistics