{"record":{"id":"92cfcf593cb491e7","repo":"WZMIAOMIAO/deep-learning-for-image-processing","slug":"object-has-no-attribute-92cfcf","errorCode":null,"errorMessage":"'{}' object has no attribute '{}'","messagePattern":"'(.+?)' object has no attribute '(.+?)'","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"pytorch_segmentation/unet/train_utils/distributed_utils.py","lineNumber":187,"sourceCode":"\nclass MetricLogger(object):\n    def __init__(self, delimiter=\"\\t\"):\n        self.meters = defaultdict(SmoothedValue)\n        self.delimiter = delimiter\n\n    def update(self, **kwargs):\n        for k, v in kwargs.items():\n            if isinstance(v, torch.Tensor):\n                v = v.item()\n            assert isinstance(v, (float, int))\n            self.meters[k].update(v)\n\n    def __getattr__(self, attr):\n        if attr in self.meters:\n            return self.meters[attr]\n        if attr in self.__dict__:\n            return self.__dict__[attr]\n        raise AttributeError(\"'{}' object has no attribute '{}'\".format(\n            type(self).__name__, attr))\n\n    def __str__(self):\n        loss_str = []\n        for name, meter in self.meters.items():\n            loss_str.append(\n                \"{}: {}\".format(name, str(meter))\n            )\n        return self.delimiter.join(loss_str)\n\n    def synchronize_between_processes(self):\n        for meter in self.meters.values():\n            meter.synchronize_between_processes()\n\n    def add_meter(self, name, meter):\n        self.meters[name] = meter\n\n    def log_every(self, iterable, print_freq, header=None):","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/WZMIAOMIAO/deep-learning-for-image-processing/blob/1ec3fe6f374fc9969973a61f819de25658595afa/pytorch_segmentation/unet/train_utils/distributed_utils.py#L169-L205","documentation":"MetricLogger.__getattr__ in unet/train_utils raises AttributeError when the requested attribute is neither a registered meter (in self.meters) nor an instance attribute. It's a deliberate fail-loud check so typos on the metric logger surface immediately.","triggerScenarios":"Accessing e.g. metric_logger.losses or metric_logger.meterss, or reading a meter that was never set via __setattr__ (never assigned a SmoothedValue) before the first update call.","commonSituations":"Typos in training scripts, reading metrics before train_one_epoch populates them, divergence between meter names in train vs eval code paths.","solutions":["Correct the attribute name to a registered meter (loss, lr, ...)","Ensure the meter is assigned before access: metric_logger.xxx = SmoothedValue()","Use hasattr(metric_logger, name) or name in metric_logger.meters before reading"],"exampleFix":"// before\nprint(metric_logger.acc.global_avg)\n// after\nprint(metric_logger.loss.global_avg)  # 'acc' was never registered on MetricLogger","handlingStrategy":"validation","validationCode":"required = ['loss', 'lr']\nmissing = [r for r in required if r not in metric_logger.meters]\nassert not missing, f\"unregistered meters: {missing}\"","typeGuard":"def meter_exists(logger, name: str) -> bool:\n    return name in logger.meters","tryCatchPattern":"try:\n    avg_loss = metric_logger.loss.global_avg\nexcept AttributeError as e:\n    avg_loss = None\n    print(f\"meter missing: {e}\")","preventionTips":["Initialize all meters in one setup function before training","Search codebase for old meter names after refactors","Prefer iterating metric_logger.meters over hardcoding attribute names"],"tags":["python","attributeerror","training-loop"],"backgroundTag":"attribute-not-found","analyzedSha":"1ec3fe6f374fc9969973a61f819de25658595afa","analyzedAt":"2026-08-30T09:19:11.901Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}