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")