Hello there!
I am trying to combine gradio with a backend based on python classes that inherit from a parent class that allow them to have customized logs and clean the context manager after finishing the execution of the class.
This is a snippet of the error I get when trying to do so:
``
File “C:\Users\AnaGonzalezGuerra\anaconda3\envs\RPA\lib\site-packages\requests\sessions.py”, line 589, in request
resp = self.send(prep, **send_kwargs)
File “C:\Users\AnaGonzalezGuerra\anaconda3\envs\RPA\lib\site-packages\requests\sessions.py”, line 703, in send
r = adapter.send(request, **kwargs)
File “C:\Users\AnaGonzalezGuerra\anaconda3\envs\RPA\lib\site-packages\requests\adapters.py”, line 486, in send
resp = conn.urlopen(
File “C:\Users\AnaGonzalezGuerra\anaconda3\envs\RPA\lib\site-packages\urllib3\connectionpool.py”, line 714, in urlopen
httplib_response = self._make_request(
File “C:\Users\AnaGonzalezGuerra\anaconda3\envs\RPA\lib\site-packages\urllib3\connectionpool.py”, line 473, in make_request
log.debug(
Message: ‘%s://%s:%s “%s %s %s” %s %s’
Arguments: (‘https’, ‘api.gradio.app’, 443, ‘POST’, ‘/gradio-launched-telemetry/’, ‘HTTP/1.1’, 200, None)
— Logging error —
Traceback (most recent call last):
File "C:\Users\AnaGonzalezGuerra\anaconda3\envs\RPA\lib\logging_init.py", line 440, in format
return self.format(record)
File "C:\Users\AnaGonzalezGuerra\anaconda3\envs\RPA\lib\logging_init.py", line 436, in _format
return self._fmt % values
KeyError: ‘process_name’
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File “C:\Users\AnaGonzalezGuerra\anaconda3\envs\RPA\lib\logging\handlers.py”, line 73, in emit
if self.shouldRollover(record):
File “C:\Users\AnaGonzalezGuerra\anaconda3\envs\RPA\lib\logging\handlers.py”, line 196, in shouldRollover
msg = “%s\n” % self.format(record)
File “C:\Users\AnaGonzalezGuerra\anaconda3\envs\RPA\lib\logging_init_.py”, line 943, in format
return fmt.format(record)
File “C:\Users\AnaGonzalezGuerra\anaconda3\envs\RPA\lib\logging_init_.py”, line 681, in format
s = self.formatMessage(record)
File “C:\Users\AnaGonzalezGuerra\anaconda3\envs\RPA\lib\logging_init_.py”, line 650, in formatMessage
return self.style.format(record)
File "C:\Users\AnaGonzalezGuerra\anaconda3\envs\RPA\lib\logging_init.py", line 442, in format
raise ValueError(‘Formatting field not found in record: %s’ % e)
ValueError: Formatting field not found in record: ‘process_name’
``
I cannot send the full message because it is an infinite loop. You can see that is saying that cannot reach the process_name argument , this is because I am adding some extra arguments in the LogDBHandler class (I customized the class adding some arguments and logging to a DB).
This happens when I try to call the following class from main:
``
class SimpleGradioInterface(activities):
def init(self, process, log_level=None):
super().init(process = process, log_level = log_level) # Call the parent constructor
self.interface = self.create_interface()
@staticmethod
def simple_function(word=""):
return "hi"
def create_interface(self):
interface = gr.Interface(
fn=self.simple_function,
inputs=gr.Textbox(label="Input", elem_classes="textbox"),
outputs=gr.Textbox(label="Output", elem_classes="textbox")
)
return interface
def launch(self):
self.interface.launch()
``
Using this code in main:
``
if name == ‘main’:
gr_interface = SimpleGradioInterface(process=process_name, log_level='DEBUG')
gr_interface.launch()
``
My best guest is there is some kind of conflict between python context manager definition, the definition I have in my parent class and the one defined in gradio, because if I do this test it seems possible the combination with the backend logs:
``
class HitActivity(activities):
@log_decorator()
def say_hello(self):
print(“Hello from HitActivity!”)
return “Greeting done!”
def wrapped_hit_activity_function(_=None):
activity = HitActivity()
try:
activity.__enter__()
result = activity.say_hello()
finally:
activity.__exit__(None, None, None)
return result
interface = gr.Interface(
fn=wrapped_hit_activity_function,
inputs=gr.Textbox(label="Input", elem_classes="textbox"),
outputs=gr.Textbox(label="Output", elem_classes="textbox")
)
interface.launch()
``
And then I get the expected output:
``
2023-10-16 17:38:36,432 - INFO - RPA Highlighter - HitActivity - Running: [Level 1] HitActivity is running - anagongue
2023-10-16 17:38:36,433 - DEBUG - RPA Highlighter - HitActivity - Running: [Level 1] Method say_hello running - anagongue
2023-10-16 17:38:36,435 - DEBUG - RPA Highlighter - HitActivity - Ended: [Level 1] Method say_hello ended successfully - anagongue
2023-10-16 17:38:36,437 - INFO - RPA Highlighter - HitActivity - Ended: [Level 1] HitActivity ended - anagongue
``
Is there some kind of consideration I should have about how gradio uses the python context manager? In my case I am using this code for defining it in the parent class and make the child classes inherit:
``
class activities(LoggingMixin, EmailNotificationMixin):
‘’’
activities class is the parent class of
the set of activities
that forms the RPA process.
It inherits from Mixins LogginMixin and EmailNotificationMixin.
All activities inherit the same arguments:
process_name, activity (activity name) and status (Start,
Running, Ended)
'''
_activity_stack = [] # list to be used to stack activities
# and keep a record of current activities in use.
# This list allows us to organize activity log sublevels
_stack_lock = Lock() # lock object
def __init__(self, process = process_name, log_level=None):
self.process = process # RPA process name
# Activity name of the RPA process, step of the process
# automatically set to the name of the class
self.activity = self.__class__.__name__
self.configure_logger(log_level)
def __enter__(self):
with self._stack_lock: # Acquire the lock
self._activity_stack.append(self.activity) # add activity to the stack
self.log_start()
self.log_running()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type and issubclass(exc_type, CriticalException): # Check if it's a critical exception
self.send_error_notification(exc_type, exc_val, exc_tb)
with self._stack_lock: # Acquire the lock
self._activity_stack.pop() # remove activity from stack to release resources
sys.exit(f"Terminating due to critical error: {exc_val}")
elif exc_type and issubclass(exc_type, GeneralException):
self.send_error_notification(exc_type, exc_val, exc_tb)
with self._stack_lock: # Acquire the lock
self._activity_stack.pop() # remove activity from stack to release resources
elif exc_type and issubclass(exc_type, WarningException):
with self._stack_lock: # Acquire the lock
self._activity_stack.pop() # remove activity from stack to release resources
else:
self.log_end(exc_type, exc_val, exc_tb)
with self._stack_lock: # Acquire the lock
self._activity_stack.pop() # remove activity from stack to release resources
``
Best regards,
Ana González Guerra