Python项目规范开发(2) 预编写脚本

都是一些功能性的脚本,可以自己编写,可以去收集后修改。反正适合自己或者自己知道如何使用。

如果没找到合适的,可以参考我这里的,如果发现我的脚本有问题,也可以提出来让我修复学习。

日志 – LOG-Handler

import os
import logging
from logging.handlers import RotatingFileHandler
from functools import wraps

LOG_DIR = 'LOGS'  # Log directory
LOG_FILE = 'app.log'  # Log file name

# Ensure the log directory exists
os.makedirs(LOG_DIR, exist_ok=True)

# Create a custom log formatter
log_format = "%(asctime)s [%(levelname)s] - %(message)s"
formatter = logging.Formatter(log_format)

# Create a rotating file handler with a max log file size of 10MB
log_handler = RotatingFileHandler(os.path.join(LOG_DIR, LOG_FILE), maxBytes=10 * 1024 * 1024, backupCount=5)
log_handler.setFormatter(formatter)

# Create a logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
logger.addHandler(log_handler)

# Define a decorator to log function calls
def log_function_call(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            logger.info(f"Calling function: {func.__name__}")
            result = func(*args, **kwargs)
            logger.info(f"Function {func.__name__} completed successfully")
            return result
        except Exception as e:
            logger.error(f"Function {func.__name__} failed with error: {str(e)}")
            raise e

    return wrapper

# Usage example:
@log_function_call
def example_function():
    print("This is an example function.")

if __name__ == "__main__":
    example_function()

测试用例 – Test-Handler

# 导入pytest库,用于编写和运行测试用例
import pytest
import os
import logging
import importlib
import sys
import DB_Handler  # 导入你的数据库处理模块
from LogHandle import log_function_call

# 使用你的数据库处理模块中的DatabaseHandler类来处理数据库连接
db_handler = your_database_handler_module.DatabaseHandler('mysql', 'localhost', 3306, 'mydb', 'root', 'password')

# Pytest夹具(fixture)用于设置数据库连接以进行测试
@pytest.fixture
def setup_database():
    db_handler.connect()  # 连接数据库
    yield db_handler  # 通过yield语句提供db_handler对象,测试用例中可以使用
    db_handler.close_connection()  # 关闭数据库连接,确保清理

# Pytest夹具用于初始化数据库并添加测试数据(如果需要)
@pytest.fixture
def init_database(setup_database):
    # 实现数据库初始化逻辑
    # 你可以使用setup_database夹具执行初始化操作
    # 例如,向数据库插入测试数据
    pass  # 这里留空,根据你的项目需要添加初始化逻辑

# 定义测试用例
def test_select_data(setup_database):
    # 测试是否能够成功从数据库中选择数据
    results = setup_database.execute_query("SELECT * FROM mytable")
    assert len(results) > 0  # 验证查询结果中是否有数据

def test_insert_data(setup_database, init_database):
    # 测试是否能够成功将数据插入数据库
    data = {
        # 定义测试数据
    }
    setup_database.insert_record("mytable", data)  # 向数据库插入数据
    # 通过选择和检查数据来验证插入操作
    results = setup_database.execute_query("SELECT * FROM mytable WHERE ...")  # 查询插入的数据
    assert len(results) > 0  # 验证查询结果中是否有数据

# 根据需要,你可以添加更多针对数据库操作的测试用例

if __name__ == "__main__":
    pytest.main(["-s", __file__])  # 运行测试并输出日志

命令行 – CommandLine-Handler

import argparse
import os
import sys
import logging
from LogHandle import log_function_call

# Define a class to handle command-line arguments and subcommands
class CommandLineTool:
    def __init__(self):
        self.parser = argparse.ArgumentParser(description="通用命令行工具")
        self.subparsers = self.parser.add_subparsers(dest="command", title="命令列表")

    def add_command(self, name, help_text, handler):
        parser = self.subparsers.add_parser(name, help=help_text)
        parser.set_defaults(handler=handler)

        @log_function_call
        def run(self):
            args = self.parser.parse_args()
        if hasattr(args, 'handler'):
            args.handler()

if __name__ == "__main__":
    # Create the command-line tool
    tool = CommandLineTool()

    # Add commands
    tool.add_command("version", "显示程序版本", lambda: print("版本号:1.0"))
    # Add more commands here

    # Run the command-line tool
    tool.run()

文件操作 – File -Handler

import os
import logging
from pathlib import Path
from LogHandle import log_function_call

# Define a class to handle file operations
class FileHandler:
    FILE_SUFFIXES = ['txt', 'csv', 'html', 'yaml']

    def __init__(self, file_path):
        self.file_path = Path(file_path)
        self.file_suffix = self.file_path.suffix[1:]  # Remove the leading dot

        @log_function_call
        def read_file(self):
            if self.file_suffix in self.FILE_SUFFIXES:
            # Add specific file reading logic based on the file type
            if self.file_suffix == 'txt':
                with self.file_path.open() as file:
                    return file.read()
            elif self.file_suffix == 'csv':
                # Implement CSV file reading logic
                pass
            elif self.file_suffix == 'html':
                # Implement HTML file reading logic
                pass
            elif self.file_suffix == 'yaml':
                # Implement YAML file reading logic
                pass
        else:
            raise ValueError("Unsupported file type")

if __name__ == "__main__":
    # Example usage
    file_handler = FileHandler("example.txt")
    try:
        file_content = file_handler.read_file()
        print(file_content)
    except Exception as e:
        print(f"Error: {str(e)}")


数据操作 – DB-Handler

import os
import logging
from logging.handlers import RotatingFileHandler
from functools import wraps
import importlib
import sys

LOG_DIR = 'LOGS'  # Log directory
LOG_FILE = 'app.log'  # Log file name

# Ensure the log directory exists
os.makedirs(LOG_DIR, exist_ok=True)

# Create a custom log formatter
log_format = "%(asctime)s [%(levelname)s] - %(message)s"
formatter = logging.Formatter(log_format)

# Create a rotating file handler with a max log file size of 10MB
log_handler = RotatingFileHandler(os.path.join(LOG_DIR, LOG_FILE), maxBytes=10 * 1024 * 1024, backupCount=5)
log_handler.setFormatter(formatter)

# Create a logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
logger.addHandler(log_handler)

# Define a decorator to log function calls
def log_function_call(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            logger.info(f"Calling function: {func.__name__}")
            result = func(*args, **kwargs)
            logger.info(f"Function {func.__name__} completed successfully")
            return result
        except Exception as e:
            logger.error(f"Function {func.__name__} failed with error: {str(e)}")
            raise e

    return wrapper

# Define a class to handle database connections and operations
class DatabaseHandler:
    DB_SUFFIXES = ['mysql', 'oracle', 'postgresql', 'redis', 'mongodb']

    def __init__(self, db_type, db_host, db_port, db_name, db_user, db_password):
        if db_type not in self.DB_SUFFIXES:
            raise ValueError("Unsupported database type")
        self.db_type = db_type
        self.db_module = importlib.import_module(db_type)
        self.db_host = db_host
        self.db_port = db_port
        self.db_name = db_name
        self.db_user = db_user
        self.db_password = db_password

    def connect(self):
        try:
            # Create a database connection based on the database type
            if self.db_type == 'mysql':
                # Implement MySQL connection logic
                pass
            elif self.db_type == 'oracle':
                # Implement Oracle connection logic
                pass
            elif self.db_type == 'postgresql':
                # Implement PostgreSQL connection logic
                pass
            elif self.db_type == 'redis':
                # Implement Redis connection logic
                pass
            elif self.db_type == 'mongodb':
                # Implement MongoDB connection logic
                pass
        except Exception as e:
            raise e

    def execute_query(self, query):
        try:
            # Execute the provided query and return results
            pass
        except Exception as e:
            raise e

    def insert_record(self, table, data):
        try:
            # Insert a record into the specified table
            pass
        except Exception as e:
            raise e

    def update_record(self, table, data):
        try:
            # Update a record in the specified table
            pass
            except Exception as e:
            raise e

            def delete_record(self, table, conditions):
            try:
            # Delete records from the specified table based on conditions
            pass
            except Exception as e:
            raise e

            if __name__ == "__main__":
    # Example usage
            db_handler = DatabaseHandler('mysql', 'localhost', 3306, 'mydb', 'root', 'password')
            try:
            db_handler.connect()
            results = db_handler.execute_query("SELECT * FROM mytable")
            print(results)
            except Exception as e:
            print(f"Error: {str(e)}")

异常处理 – Exception-Handler

from sanic.exceptions import SanicException
from utils import json

# 自定义异常类,用于处理与安全性相关的错误


class SecurityError(SanicException):
    """
    Sanic 安全相关错误。
    属性:
        json (HTTPResponse): 安全错误的 JSON 响应。
    Args:
        message (str): 人类可读的错误消息。
        code (int): HTTP 错误码。
    """

    def __init__(self, message: str, code: int):
        self.json = json(message, self.__class__.__name__, code)
        super().__init__(message, code)

# 当资源无法找到时引发的异常


class NotFoundError(SecurityError):
    """
    当资源无法找到时引发。
    Args:
        message (str): 错误消息。
    """

    def __init__(self, message):
        super().__init__(message, 404)

# 当尝试访问已删除资源时引发的异常


class DeletedError(SecurityError):
    """
    尝试访问已删除资源时引发。

    Args:
        message (str): 错误消息。
    """

    def __init__(self, message):
        super().__init__(message, 410)

# 所有其他帐户错误派生自的基本帐户错误


class AccountError(SecurityError):
    """
    所有其他帐户错误派生自的基本帐户错误。

    Args:
        message (str): 错误消息。
        code (int): HTTP 错误码。
    """

    def __init__(self, message, code):
        super().__init__(message, code)

# 当帐户被禁用时引发的异常


class DisabledError(AccountError):
    """
    当帐户被禁用时引发。

    Args:
        message (str): 错误消息,默认为 "Account is disabled."。
        code (int): HTTP 错误码,默认为 401。
    """

    def __init__(self, message: str = "Account is disabled.", code: int = 401):
        super().__init__(message, code)

# 当帐户未验证时引发的异常


class UnverifiedError(AccountError):
    """
    当帐户未验证时引发。

    Args:
        message (str): 默认为 "Account requires verification."。
    """

    def __init__(self):
        super().__init__("Account requires verification.", 401)

# 当帐户已验证时引发的异常


class VerifiedError(AccountError):
    """
    当帐户已验证时引发。

    Args:
        message (str): 默认为 "Account already verified."。
    """

    def __init__(self):
        super().__init__("Account already verified.", 403)

# 所有其他会话错误派生自的基本会话错误


class SessionError(SecurityError):
    """
    所有其他会话错误派生自的基本会话错误。

    Args:
        message (str): 错误消息。
        code (int): HTTP 错误码,默认为 401。
    """

    def __init__(self, message, code=401):
        super().__init__(message, code)

# 当客户端 JWT 无效时引发的异常


class JWTDecodeError(SessionError):
    """
    当客户端 JWT 无效时引发。

    Args:
        message (str): 错误消息,默认为 400。
    """

    def __init__(self, message, code=400):
        super().__init__(message, code)

# 当会话被停用时引发的异常


class DeactivatedError(SessionError):
    """
    当会话被停用时引发。

    Args:
        message (str): 默认为 "Session is deactivated."。
        code (int): HTTP 错误码,默认为 401。
    """

    def __init__(self, message: str = "Session is deactivated.", code: int = 401):
        super().__init__(message, code)

# 当会话已过期时引发的异常


class ExpiredError(SessionError):
    """
    当会话已过期时引发。

    Args:
        message (str): 默认为 "Session has expired"。
    """

    def __init__(self):
        super().__init__("Session has expired")

# 当身份验证会话的两因素要求未满足时引发的异常


class SecondFactorRequiredError(SessionError):
    """
    当身份验证会话的两因素要求未满足时引发。

    Args:
        message (str): 默认为 "Session requires second factor for authentication."。
    """

    def __init__(self):
        super().__init__("Session requires second factor for authentication.")

# 当身份验证会话的两因素要求已满足时引发的异常


class SecondFactorFulfilledError(SessionError):
    """
    当身份验证会话的两因素要求已满足时引发。

    Args:
        message (str): 默认为 "Session second factor requirement already met."。
        code (int): HTTP 错误码,默认为 403。
    """

    def __init__(self):
        super().__init__("Session second factor requirement already met.", 403)

# 当会话挑战尝试无效时引发的异常


class ChallengeError(SessionError):
    """
    当会话挑战尝试无效时引发。

    Args:
        message (str): 错误消息。
    """

    def __init__(self, message):
        super().__init__(message)

# 当会话的挑战尝试次数达到上限时引发的异常


class MaxedOutChallengeError(ChallengeError):
    """
    当会话的挑战尝试次数达到上限时引发。

    Args:
        message (str): 默认为 "The maximum amount of attempts has been reached."。
    """

    def __init__(self):
        super().__init__("The maximum amount of attempts has been reached.")

# 当帐户权限或角色不足以执行操作时引发的异常


class AuthorizationError(SecurityError):
    """
    当帐户权限或角色不足以执行操作时引发。

    Args:
        message (str): 错误消息。
    """

    def __init__(self, message):
        super().__init__(message, 403)

# 当凭据无效时引发的异常


class CredentialsError(SecurityError):
    """
    当凭据无效时引发。
    Args:
        message (str): 错误消息,默认为 400。
        code (int): HTTP 错误码,默认为 400。
    """

    def __init__(self, message, code=400):
        super().__init__(message, code)

配置文件处理 – Config-Handler

import json
import pathlib
CONFIG_FILE_FORMATS = ['yaml', 'toml', 'conf', 'ini']


class ConfigurationHandler:
    def __init__(self, config_file_path):
        self.config_file_path = pathlib.Path(config_file_path)
        self.validate_config_file()
    
    def validate_config_file(self):
        # Check if the config file exists
        if not self.config_file_path.exists():
            raise FileNotFoundError(f"Config file not found: {str(self.config_file_path)}")

        # Check if the file extension is supported
        file_extension = self.config_file_path.suffix.lstrip('.')
        if file_extension not in CONFIG_FILE_FORMATS:
            raise ValueError(f"Unsupported config file format: {file_extension}")

    def _read_yaml(self, filepath):
        import yaml
        with open(filepath, 'r') as f:
            config_data = yaml.load(f, Loader=yaml.FullLoader)
            return config_data

    def _read_toml(self, filepath):
        import toml as toml_module
        pass
        
    def _read_conf(self, filepath):
        import configparser
        pass
        
    def _read_ini(self, filepath):
        import pyhocon as hocon
        pass
        
    def read_config(self):
        config_data = {}
        file_extension = self.config_file_path.suffix.lstrip('.')
    	if file_extension == 'yaml':
            config_data = self._read_yaml(str(self.config_file_path))
		elif file_extension == 'toml':
            config_data = self._read_toml(str(self.config_file_path))
		elif file_extension == 'conf':
            config_data = self._read_conf(str(self.config_file_path))
		elif file_extension == 'ini':
            config_data = self._read_ini(str(self.config_file_path))
        
        # Convert the data to JSON format
        json_config = json.dumps(config_data, indent=4)
        return json_config

# Usage example
if __name__ == "__main__":
    config_file_path = 'config.yaml'  # Provide the path to your config file
    config_handler = ConfigurationHandler(config_file_path)
    json_config = config_handler.read_config()
    print(json_config)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值