python的上下文管理器

文章探讨了使用上下文管理器在Python中进行文件操作的重要性,防止资源泄露。它展示了如何通过自定义类和生成器实现上下文管理器,以及如何在Django框架中利用上下文管理器改进异常处理,确保文件正确关闭和错误妥善处理。此外,还介绍了如何使用contextlib创建临时目录并在完成后自动删除。
摘要由CSDN通过智能技术生成

1.为什么使用上下文管理器

循环打开1000万个文件,且用完之后不关闭,会照成资源泄露,并报如下错

OSError:[Errno 23] Too many open files in system 'test.txt'

2.基于类的上下文

1.实现文件的打开和关闭

class FileManager:

    def __init__(self, name, mode):
        print("calling __init__ method")
        self.name = name
        self.mode = mode
        self.file = None

    def __enter__(self):
        print('calling __enter__ method')
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('calling __exit__ method')
        if self.file:
            self.file.close()

        return True
  

2.使用上下文改善异常处理

from django.http import HttpResponse


class ErrorCodes:
    AVATAR_FILE_NOT_PROVIDED = "not file provide"


class RaiseApiError:
    def __init__(self, captures, code_name):
        self.captures = captures
        self.code = getattr(ErrorCodes, code_name)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type is None:
            return False

        if exc_type == self.captures:
            raise self.code from exc_val

        return False


def upload_avatar(request):
    """用户上传新头像"""
    with RaiseApiError(KeyError, 'AVATAR_FILE_NOT_PROVIDED'):
        avatar_file = request.FILES['avatar']

    with RaiseApiError(ResizeAvatarError, 'AVATAR_FILE_INVALID'), RaiseApiError(FileTooLargeError,
                                                                                'AVATAR_FILE_TOO_LARGE'):
        resized_avatar_file = resize_avatar(avatar_file)

    with RaiseApiError(Exception, 'INTERNAL_SERVER_ERROR'):
        request.user.avatar = resized_avatar_file
        request.user.save()

    return HttpResponse({})

3.基于生成器的上下文

1.实现文件的打开和关闭

import contextlib


@contextlib.contextmanager
def open_func(file_name):
    # __enter__方法
    print('open file:', file_name, 'in __enter__')
    file_handler = open(file_name, 'r')

    # yield
    yield file_handler

    # __exit__方法
    print('close file:', file_name, 'in __exit__')
    file_handler.close()
    return


with open_func('test.txt') as file_in:
    for line in file_in:
        print(line)

2.创建临时目录,使用完后再删除临时目录

import contextlib
import shutil
import tempfile


@contextlib.contextmanager
def tempdir(file_path):
    temp_dir = tempfile.mktemp(file_path)
    try:
        yield temp_dir
    finally:
        try:
            shutil.rmtree(temp_dir)
        except OSError as error:
            print("Could not remove tmpdir:%s")

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值