I found this useful decorator that allows you to pass in some optional arguments
def mlflow_experiment(
_func=None,
*,
experiment_name=None
):
def experiment_decorator(func):
@functools.wraps(func)
def experiment_wrapper(self, *args, **kwargs):
nonlocal experiment_name
experiment_id = (
mlflow.set_experiment(experiment_name)
if experiment_name is not None
else None
)
...
value = func(self, *args, **kwargs)
return value
return experiment_wrapper
if _func is None:
return experiment_decorator
else:
return experiment_decorator(_func)
So in a use case like this where I just pass in a string to experiment_name
, the code works flawlessly.
@mlflow_experiment(autolog=True, experiment_name = 'blarg')
def train_mlflow(self, maxevals=50, model_id=0):
...
I've always had a hard time figuring out scope in decorators but I wasn't surprised that using passing an instance variable defined in __init__
does NOT work.
class LGBOptimizerMlfow:
def __init__(self, arg):
self.arg = arg
@mlflow_experiment(autolog=True, experiment_name = self.arg)
def train_mlflow(self, maxevals=50, model_id=0):
...
>>> `NameError: name 'self' is not defined`
Just to see if scoping was an issue, I declared the variable outside the class and it worked.
And just for the heck of it I decided to declare a global variable inside the class which also works but its less than ideal, especially if I want to pass it into the class or a method as a optional argument.
class LGBOptimizerMlfow:
global arg
arg = 'hi'
@mlflow_experiment(autolog=True, experiment_name = arg)
def train_mlflow(self, maxevals=50, model_id=0):
...
Any help to revise the code so that the decorator accepts an instance variable would be lovely.
Thank you!