SoFunction
Updated on 2025-03-10

Detailed explanation of general tool classes and exception handling in Python

In Python development, writing reusable tool classes and general exception handling mechanisms is the key to improving code quality and development efficiency. This article will introduce how to rewrite a specific exception class GlueValidaionException into a more general ValidationException and create a common tool class Utils that contains commonly used file operations and data processing methods. Finally, we will show how to use these tools through code examples.

1. General exception class: ValidationException

First, we rewrite the GlueValidaionException to a more general ValidationException to make it suitable for various verification scenarios.

class ValidationException(Exception):
    """
     General verification exception class, suitable for various verification scenarios.
     """
    def __init__(self, err_message, excep_obj):
        message = ("[Invalid input detected]\n"
                   f"Exception: {err_message}\n"
                   f"Exception logs: {excep_obj}")
        super().__init__(message)

2. General Tool Class: Utils

Next, we create a common tool class Utils, which contains common file operations and data processing methods.

import json
from  import join
from typing import Dict, List
import yaml

class Utils:
    @staticmethod
    def yaml_to_dict(file_path: str) -> Dict:
        """
         Convert YAML file to a dictionary.
        
         :param file_path: YAML file path
         :return: parsed dictionary
         """
        with open(file_path) as yaml_file:
            yaml_string = yaml_file.read()
            try:
                parsed_dict = yaml.safe_load(yaml_string)
            except  as e:
                raise ValidationException(f"YAMLFile syntax error: {file_path}", e)
        return parsed_dict

    @staticmethod
    def yaml_to_class(yaml_file_path: str, cls: type, default_yaml_file_path: str = None):
        """
         Convert YAML file to class object.
        
         :param yaml_file_path: YAML file path
         :param cls: target class
         :param default_yaml_file_path: Default YAML file path
         :return: class object
         """
        if not yaml_file_path:
            yaml_file_path = default_yaml_file_path
        custom_args = Utils.yaml_to_dict(yaml_file_path)

        if default_yaml_file_path:
            default_args = Utils.yaml_to_dict(default_yaml_file_path)
            missing_args = set(default_args) - set(custom_args)
            for key in list(missing_args):
                custom_args[key] = default_args[key]

        try:
            yaml_as_class = cls(**custom_args)
        except TypeError as e:
            raise ValidationException(f"YAMLFile conversion to class failed: {yaml_file_path}", e)

        return yaml_as_class

    @staticmethod
    def read_jsonl(file_path: str) -> List:
        """
         Read the JSONL file and return a list of all JSON objects.
        
         :param file_path: JSONL file path
         :return: JSON object list
         """
        jsonl_list = []
        with open(file_path, "r") as fileobj:
            while True:
                single_row = ()
                if not single_row:
                    break
                json_object = (single_row.strip())
                jsonl_list.append(json_object)
        return jsonl_list

    @staticmethod
    def read_jsonl_row(file_path: str):
        """
         Read the JSONL file line by line and return the JSON object.
        
         :param file_path: JSONL file path
         :return: JSON object generator
         """
        with open(file_path, "r") as fileobj:
            while True:
                try:
                    single_row = ()
                    if not single_row:
                        break
                    json_object = (single_row.strip())
                    yield json_object
                except  as e:
                    print(f"JSONLFile reading error: {file_path}. mistake: {e}")
                    continue

    @staticmethod
    def append_as_jsonl(file_path: str, args_to_log: Dict):
        """
         Append the dictionary to the JSONL file.
        
         :param file_path: JSONL file path
         :param args_to_log: Dictionary to be appended
         """
        json_str = (args_to_log, default=str)
        with open(file_path, "a") as fileobj:
            (json_str + "\n")

    @staticmethod
    def save_jsonlist(file_path: str, json_list: List, mode: str = "a"):
        """
         Save the list of JSON objects to a JSONL file.
        
         :param file_path: JSONL file path
         :param json_list: JSON object list
         :param mode: file writing mode
         """
        with open(file_path, mode) as file_obj:
            for json_obj in json_list:
                json_str = (json_obj, default=str)
                file_obj.write(json_str + "\n")

    @staticmethod
    def str_list_to_dir_path(str_list: List[str]) -> str:
        """
         Stitch the string list into directory paths.
        
         :param str_list: string list
         :return: The directory path after splicing
         """
        if not str_list:
            return ""
        path = ""
        for dir_name in str_list:
            path = join(path, dir_name)
        return path

3. Sample file content

The following are the contents of the sample file, including default_config.yaml, and.

default_config.yaml

name: "default_name"
value: 100
description: "This is a default configuration."

name: "custom_name"
value: 200

{"id": 1, "name": "Alice", "age": 25}
{"id": 2, "name": "Bob", "age": 30}
{"id": 3, "name": "Charlie", "age": 35}

4. Code example

Here is an example of how to use the Utils tool class:

# Sample Classclass Config:
    def __init__(self, name, value, description=None):
         = name
         = value
         = description

# Example 1: Convert YAML file to dictionaryyaml_dict = Utils.yaml_to_dict("")
print("Convert YAML file to dictionary:", yaml_dict)

# Example 2: Converting YAML file to class objectconfig_obj = Utils.yaml_to_class("", Config, "default_config.yaml")
print("Convert YAML file to class object:", config_obj.name, config_obj.value, config_obj.description)

# Example 3: Reading JSONL filejsonl_list = Utils.read_jsonl("")
print("Read JSONL file:", jsonl_list)

# Example 4: Reading JSONL file line by lineprint("Read JSONL file line by line:")
for json_obj in Utils.read_jsonl_row(""):
    print(json_obj)

# Example 5: Append dictionary to JSONL fileUtils.append_as_jsonl("", {"id": 4, "name": "David", "age": 40})
print("Append data to JSONL file completed")

# Example 6: Save the JSON object list to a JSONL fileUtils.save_jsonlist("", [{"id": 5, "name": "Eve", "age": 45}])
print("Save JSON list to JSONL file completed")

# Example 7: Stitching a list of strings into directory pathspath = Utils.str_list_to_dir_path(["dir1", "dir2", "dir3"])
print("Sticking directory path:", path)

5. Operation results

After running the above code, the output result is as follows:

Convert YAML file to dictionary: {'name': 'custom_name', 'value': 200}
Convert YAML file to class object: custom_name 200 This is a default configuration.
Read JSONL file: [{'id': 1, 'name': 'Alice', 'age': 25}, {'id': 2, 'name': 'Bob', 'age': 30}, {'id': 3, 'name': 'Charlie', 'age': 35}]
Read JSONL files line by line:
{'id': 1, 'name': 'Alice', 'age': 25}
{'id': 2, 'name': 'Bob', 'age': 30}
{'id': 3, 'name': 'Charlie', 'age': 35}
Append data to JSONL file to complete
Save the JSON list to the JSONL file to complete
Splicing directory path: dir1/dir2/dir3

6. Complete code

import json
from  import join
from typing import Dict, List

import yaml
from  import ScannerError


class ValidationException(Exception):
    """
     General verification exception class, suitable for various verification scenarios.
     """

    def __init__(self, err_message, excep_obj):
        message = ("[Invalid input detected]\n"
                   f"Exception: {err_message}\n"
                   f"Exception logs: {excep_obj}")
        super().__init__(message)


class Utils:
    @staticmethod
    def yaml_to_dict(file_path: str) -> Dict:
        """
         Convert YAML file to a dictionary.

         :param file_path: YAML file path
         :return: parsed dictionary
         """
        with open(file_path) as yaml_file:
            yaml_string = yaml_file.read()
            try:
                parsed_dict = yaml.safe_load(yaml_string)
            except ScannerError as e:
                raise ValidationException(f"YAMLFile syntax error: {file_path}", e)
        return parsed_dict

    @staticmethod
    def yaml_to_class(yaml_file_path: str, cls: type, default_yaml_file_path: str = None):
        """
         Convert YAML file to class object.

         :param yaml_file_path: YAML file path
         :param cls: target class
         :param default_yaml_file_path: Default YAML file path
         :return: class object
         """
        if not yaml_file_path:
            yaml_file_path = default_yaml_file_path
        custom_args = Utils.yaml_to_dict(yaml_file_path)

        if default_yaml_file_path:
            default_args = Utils.yaml_to_dict(default_yaml_file_path)
            missing_args = set(default_args) - set(custom_args)
            for key in list(missing_args):
                custom_args[key] = default_args[key]

        try:
            yaml_as_class = cls(**custom_args)
        except TypeError as e:
            raise ValidationException(f"YAMLFile conversion to class failed: {yaml_file_path}", e)

        return yaml_as_class

    @staticmethod
    def read_jsonl(file_path: str) -> List:
        """
         Read the JSONL file and return a list of all JSON objects.

         :param file_path: JSONL file path
         :return: JSON object list
         """
        jsonl_list = []
        with open(file_path, "r") as file_obj:
            while True:
                single_row = file_obj.readline()
                if not single_row:
                    break
                json_obj = (single_row.strip())
                jsonl_list.append(json_obj)
        return jsonl_list

    @staticmethod
    def read_jsonl_row(file_path: str):
        """
         Read the JSONL file line by line and return the JSON object.

         :param file_path: JSONL file path
         :return: JSON object generator
         """
        with open(file_path, "r") as file_object:
            while True:
                try:
                    single_row = file_object.readline()
                    if not single_row:
                        break
                    json_obj = (single_row.strip())
                    yield json_obj
                except  as e:
                    print(f"JSONLFile reading error: {file_path}. mistake: {e}")
                    continue

    @staticmethod
    def append_as_jsonl(file_path: str, args_to_log: Dict):
        """
         Append the dictionary to the JSONL file.

         :param file_path: JSONL file path
         :param args_to_log: Dictionary to be appended
         """
        json_str = (args_to_log, default=str)
        with open(file_path, "a") as file_object:
            file_object.write(json_str + "\n")

    @staticmethod
    def save_jsonlist(file_path: str, json_list: List, mode: str = "a"):
        """
         Save the list of JSON objects to a JSONL file.

         :param file_path: JSONL file path
         :param json_list: JSON object list
         :param mode: file writing mode
         """
        with open(file_path, mode) as file_obj:
            for json_obj in json_list:
                json_str = (json_obj, default=str)
                file_obj.write(json_str + "\n")

    @staticmethod
    def str_list_to_dir_path(str_list: List[str]) -> str:
        """
         Stitch the string list into directory paths.

         :param str_list: string list
         :return: The directory path after splicing
         """
        if not str_list:
            return ""
        dir_path = ""
        for dir_name in str_list:
            dir_path = join(dir_path, dir_name)
        return dir_path


# Sample Classclass Config:
    def __init__(self, name, value, description=None):
         = name
         = value
         = description


# Example 1: Convert YAML file to dictionaryyaml_dict = Utils.yaml_to_dict("")
print("Convert YAML file to dictionary:", yaml_dict)

# Example 2: Converting YAML file to class objectconfig_obj = Utils.yaml_to_class("", Config, "default_config.yaml")
print("Convert YAML file to class object:", config_obj.name, config_obj.value, config_obj.description)

# Example 3: Reading JSONL filejsonl_list = Utils.read_jsonl("")
print("Read JSONL file:", jsonl_list)

# Example 4: Reading JSONL file line by lineprint("Read JSONL file line by line:")
for json_obj in Utils.read_jsonl_row(""):
    print(json_obj)

# Example 5: Append dictionary to JSONL fileUtils.append_as_jsonl("", {"id": 4, "name": "David", "age": 40})
print("Append data to JSONL file completed")

# Example 6: Save the JSON object list to a JSONL fileUtils.save_jsonlist("", [{"id": 5, "name": "Eve", "age": 45}])
print("Save JSON list to JSONL file completed")

# Example 7: Stitching a list of strings into directory pathspath = Utils.str_list_to_dir_path(["dir1", "dir2", "dir3"])
print("Sticking directory path:", path)

7. Summary

By rewriting specific exception classes into general ValidationException and creating a Utils tool class containing common methods, we can greatly improve the reusability and maintainability of our code. The code examples provided in this article show how to use these tool classes for file manipulation and data processing, suitable for beginner Python programmers to learn and refer to.

This is the end of this article about detailed explanation of general tool classes and exception handling in Python. For more related contents of general tool classes and exception handling in Python, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!