pythoncythonros2cythonize

Cannot log in ROS2 node after building with cython


I have ROS2 package written in python (with usage of rclpy) with ROS2 node. Inside this node I want to use node logger, lets say in following way:

def __init__(self):
    self.get_logger().info("Starting my node!")
    self.get_logger().warn("My node has already started!")

This works perfectly with standard python build, but when I want to build it using Cython (because code is going to production) I encounter error: Logger severity cannot be changed between calls. This is caused by implementation of CallerId:

class CallerId(
        namedtuple('CallerId', ['function_name', 'file_path', 'line_number', 'last_index'])):

    def __new__(cls, frame=None):
        if not frame:
            frame = _find_caller(inspect.currentframe())
        return super(CallerId, cls).__new__(
            cls,
            function_name=frame.f_code.co_name,
            file_path=os.path.abspath(inspect.getframeinfo(frame).filename),
            line_number=frame.f_lineno,
            last_index=frame.f_lasti,  # To distinguish between two callers on the same line
        )

in file rcutils_logger.py. I understand perfectly that after "cythonization" of file my inspect module won't work anymore (because every call to inspect functions returns same line/file), but I am unable to fix it. Has anyone encountered similar problems before?


Solution

  • Thank you all for the suggestions. I've managed to implement something that satisfies my needs but isn't actually a solution to the problem.

    I've implemented a simple wrapper around Node, which overloads the get_logger method, thus creating a new one on each call, so it means that assuming you don't access the logger by saving it in a variable every logger has exactly one call with same severity.

    from uuid import uuid4
    
    from rclpy.impl.rcutils_logger import RcutilsLogger as RosLogger
    from rclpy.node import Node
    
    
    class NodeAdapter(Node):
        def __init__(self, node_name: str, *args, **kwargs) -> None:
            super().__init__(node_name, *args, **kwargs)
    
        def get_logger(self) -> RosLogger:
            unique_logger_name = f"{uuid4()}"
            return self._logger.get_child(unique_logger_name)