发布于2026-05-31 阅读(0)
扫一扫,手机访问
资源管理是Python编程里绕不开的一个话题。不管是处理文件、维护网络连接,还是操作数据库,用完后都得把资源老老实实释放掉。Python的with语句提供了一个既优雅又安全的方式来自动完成这些事,尤其是在文件操作中,它的优势特别明显。

with语句是Python中专门用于上下文管理的关键字。它的核心思想是:当你进入一段代码块时自动执行一些初始化操作,退出时再自动执行清理操作。这套机制基于上下文管理器协议,只要实现了__enter__和__exit__两个方法,任何对象都可以成为上下文管理器。
with expression as variable:
# 代码块
pass
也可以同时管理多个上下文:
with expression1 as var1, expression2 as var2:
# 代码块
pass
在深入讨论with之前,不妨先回顾一下传统文件操作方式有哪些让人头疼的地方。
# 传统方式:手动打开和关闭文件
file = open('example.txt', 'r')
content = file.read()
print(content)
file.close() # 必须手动关闭文件
写法倒是简单,但隐患不小:
file.close()根本不会被执行。close()。def read_file_traditional(filename):
"""传统方式读取文件,展示潜在问题"""
file = open(filename, 'r')
try:
content = file.read()
# 模拟一个可能导致异常的操作
result = 1 / 0 # 这会引发ZeroDivisionError
return content
finally:
file.close() # 即使有异常也会执行
# 调用函数
try:
read_file_traditional('nonexistent.txt')
except Exception as e:
print(f"捕获到异常: {e}")
虽然try-finally能解决一部分问题,但代码变得又长又绕,读起来费劲。
with语句通过上下文管理器协议把这些麻烦一网打尽:
try-finally。# 使用with语句读取文件
with open('example.txt', 'r') as file:
content = file.read()
print(content)
# 文件在此处自动关闭,无需手动调用close()
# 写入文件
with open('output.txt', 'w') as file:
file.write('Hello, World!')
# 文件自动关闭
任何实现了__enter__和__exit__方法的对象都可以作为上下文管理器使用。看一个简单的自定义例子:
class MyContextManager:
def __enter__(self):
print("进入上下文")
return self
def __exit__(self, exc_type, exc_value, traceback):
print("退出上下文")
if exc_type is not None:
print(f"发生了异常: {exc_type.__name__}: {exc_value}")
return False # 返回False表示不抑制异常
# 使用自定义上下文管理器
with MyContextManager() as cm:
print("在上下文中执行代码")
# raise ValueError("测试异常") # 取消注释测试异常处理
__exit__方法接收四个参数:
exc_type:异常类型(没有异常则为None)exc_value:异常值(没有异常则为None)traceback:回溯对象(没有异常则为None)class ExceptionSuppressor:
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
if exc_type is not None:
print(f"捕获并抑制了异常: {exc_type.__name__}: {exc_value}")
return True # 抑制异常
return False
# 测试异常抑制
with ExceptionSuppressor():
print("开始执行...")
raise ValueError("这是一个测试异常")
print("这行不会执行")
print("程序继续执行")
# 读取文本文件
def read_text_file(filename):
with open(filename, 'r', encoding='utf-8') as file:
return file.read()
# 写入JSON数据
import json
def write_json_data(data, filename):
with open(filename, 'w', encoding='utf-8') as file:
json.dump(data, file, indent=2, ensure_ascii=False)
# 读取JSON数据
def read_json_data(filename):
with open(filename, 'r', encoding='utf-8') as file:
return json.load(file)
# 示例使用
data = {
"name": "张三",
"age": 30,
"city": "北京"
}
write_json_data(data, 'user.json')
loaded_data = read_json_data('user.json')
print(loaded_data)
# 复制二进制文件
def copy_binary_file(source, destination):
with open(source, 'rb') as src_file:
with open(destination, 'wb') as dst_file:
while True:
chunk = src_file.read(1024) # 每次读取1KB
if not chunk:
break
dst_file.write(chunk)
# 使用示例
# copy_binary_file('source.jpg', 'destination.jpg')
# 同时打开多个文件进行处理
def process_multiple_files(input_file, output_file, log_file):
with open(input_file, 'r') as infile,
open(output_file, 'w') as outfile,
open(log_file, 'w') as logfile:
for line_num, line in enumerate(infile, 1):
try:
# 处理每一行
processed_line = line.strip().upper()
outfile.write(processed_line + 'n')
if line_num % 100 == 0:
logfile.write(f"已处理 {line_num} 行n")
except Exception as e:
logfile.write(f"第 {line_num} 行处理出错: {e}n")
# 创建测试数据
test_data = [f"这是第{i}行数据n" for i in range(1, 1001)]
with open('input.txt', 'w') as f:
f.writelines(test_data)
# 处理文件
process_multiple_files('input.txt', 'output.txt', 'process.log')
import os
import time
class FileLock:
def __init__(self, lock_file):
self.lock_file = lock_file
def __enter__(self):
# 等待获取锁
while os.path.exists(self.lock_file):
time.sleep(0.1)
# 创建锁文件
with open(self.lock_file, 'w') as f:
f.write(str(os.getpid()))
return self
def __exit__(self, exc_type, exc_value, traceback):
# 删除锁文件
if os.path.exists(self.lock_file):
os.remove(self.lock_file)
# 使用文件锁
def critical_operation():
with FileLock('operation.lock'):
print("执行关键操作...")
time.sleep(2) # 模拟耗时操作
print("操作完成")
# 在不同线程或进程中调用critical_operation()
class DatabaseConnection:
def __init__(self, connection_string):
self.connection_string = connection_string
self.connection = None
def __enter__(self):
print(f"连接到数据库: {self.connection_string}")
# 这里应该是实际的数据库连接代码
self.connection = f"连接对象({self.connection_string})"
return self.connection
def __exit__(self, exc_type, exc_value, traceback):
print("关闭数据库连接")
# 这里应该是实际的关闭连接代码
self.connection = None
# 使用数据库连接
def query_database():
with DatabaseConnection("postgresql://localhost/mydb") as conn:
print(f"使用连接: {conn}")
# 执行数据库查询...
return "查询结果"
result = query_database()
import urllib.request
from contextlib import contextmanager
@contextmanager
def web_request(url):
print(f"发起请求: {url}")
response = None
try:
response = urllib.request.urlopen(url)
yield response
except Exception as e:
print(f"请求失败: {e}")
raise
finally:
if response:
response.close()
print("响应已关闭")
# 使用网络请求上下文管理器
def fetch_web_content(url):
try:
with web_request(url) as response:
content = response.read().decode('utf-8')
return content[:200] + "..." # 只返回前200个字符
except Exception as e:
return f"获取内容失败: {e}"
# 注意:实际使用时请替换为可访问的URL
# content = fetch_web_content('https://httpbin.org/get')
# print(content)
Python标准库中的contextlib模块提供了大量实用工具来简化上下文管理器的创建和使用。
from contextlib import contextmanager
import time
@contextmanager
def timer():
start_time = time.time()
print("计时开始")
try:
yield
finally:
end_time = time.time()
print(f"耗时: {end_time - start_time:.2f} 秒")
# 使用timer上下文管理器
with timer():
time.sleep(1) # 模拟耗时操作
print("执行一些任务...")
@contextmanager
def temporary_change_dir(new_dir):
import os
old_dir = os.getcwd()
try:
os.chdir(new_dir)
yield
finally:
os.chdir(old_dir)
# 使用临时目录切换
# with temporary_change_dir('/tmp'):
# print(f"当前目录: {os.getcwd()}")
# print(f"恢复目录: {os.getcwd()}")
from contextlib import suppress
import os
# 抑制特定异常
with suppress(FileNotFoundError):
with open('nonexistent.txt', 'r') as f:
content = f.read()
print("文件内容:", content)
# 抑制多个异常类型
with suppress(FileNotFoundError, PermissionError):
os.remove('protected_file.txt')
print("文件删除成功")
from contextlib import redirect_stdout, redirect_stderr
import io
import sys
# 重定向标准输出
output_buffer = io.StringIO()
with redirect_stdout(output_buffer):
print("这条消息被重定向了")
print("这条也是")
captured_output = output_buffer.getvalue()
print(f"捕获的输出: {captured_output}")
# 重定向标准错误
error_buffer = io.StringIO()
with redirect_stderr(error_buffer):
print("错误信息", file=sys.stderr)
captured_error = error_buffer.getvalue()
print(f"捕获的错误: {captured_error}")
通过一个简单的基准测试来比较不同文件操作方式的性能差异:
import time
import tempfile
import os
def traditional_file_handling(filename, iterations=1000):
"""传统文件处理方式"""
start_time = time.time()
for i in range(iterations):
file = open(filename, 'a')
file.write(f"Line {i}n")
file.close()
return time.time() - start_time
def with_statement_handling(filename, iterations=1000):
"""使用with语句的文件处理方式"""
start_time = time.time()
for i in range(iterations):
with open(filename, 'a') as file:
file.write(f"Line {i}n")
return time.time() - start_time
def contextlib_handling(filename, iterations=1000):
"""使用contextlib的文件处理方式"""
from contextlib import closing
start_time = time.time()
for i in range(iterations):
with closing(open(filename, 'a')) as file:
file.write(f"Line {i}n")
return time.time() - start_time
# 创建临时文件进行测试
temp_file = tempfile.NamedTemporaryFile(delete=False)
temp_filename = temp_file.name
temp_file.close()
try:
# 执行性能测试
traditional_time = traditional_file_handling(temp_filename)
with_time = with_statement_handling(temp_filename)
contextlib_time = contextlib_handling(temp_filename)
print("性能对比结果:")
print(f"传统方式: {traditional_time:.4f} 秒")
print(f"with语句: {with_time:.4f} 秒")
print(f"contextlib: {contextlib_time:.4f} 秒")
finally:
# 清理临时文件
os.unlink(temp_filename)
渲染错误: Mermaid 渲染失败: Parse error on line 6: ... B --> B1[open()] B --> B2[rea ----------------------^ Expecting 'SQE', 'DOUBLECIRCLEEND', 'PE', '-)', 'STADIUMEND', 'SUBROUTINEEND', 'PIPE', 'CYLINDEREND', 'DIAMOND_STOP', 'TAGEND', 'TRAPEND', 'INVTRAPEND', 'UNICODE_TEXT', 'TEXT', 'TAGSTART', got 'PS'
# 推荐:明确指定编码
with open('file.txt', 'r', encoding='utf-8') as f:
content = f.read()
# 不推荐:依赖系统默认编码
with open('file.txt', 'r') as f:
content = f.read()
# 推荐:使用原始字符串处理路径
with open(r'C:pathtofile.txt', 'r') as f:
content = f.read()
# 处理大文件时使用迭代器
def process_large_file(filename):
with open(filename, 'r', encoding='utf-8') as f:
for line in f: # 逐行读取,避免内存溢出
process_line(line.strip())
def process_line(line):
# 处理单行数据
pass
def robust_file_operation(filename):
try:
with open(filename, 'r', encoding='utf-8') as f:
return f.read()
except FileNotFoundError:
print(f"文件 {filename} 不存在")
return None
except PermissionError:
print(f"没有权限访问文件 {filename}")
return None
except UnicodeDecodeError:
print(f"文件 {filename} 编码错误,尝试其他编码")
try:
with open(filename, 'r', encoding='gbk') as f:
return f.read()
except Exception:
print("无法解码文件")
return None
except Exception as e:
print(f"读取文件时发生未知错误: {e}")
return None
import gc
import weakref
class ResourceTracker:
def __init__(self):
self.resources = weakref.WeakSet()
def track(self, resource):
self.resources.add(resource)
return resource
def get_leaked_resources(self):
# 强制垃圾回收
gc.collect()
return len(self.resources)
# 全局资源跟踪器
tracker = ResourceTracker()
class TrackedFile:
def __init__(self, filename, mode):
self.file = open(filename, mode)
self.filename = filename
print(f"打开文件: {filename}")
def __enter__(self):
return tracker.track(self.file)
def __exit__(self, exc_type, exc_value, traceback):
print(f"关闭文件: {self.filename}")
self.file.close()
# 使用跟踪的文件操作
with TrackedFile('test.txt', 'w') as f:
f.write('Hello, World!')
leaked_count = tracker.get_leaked_resources()
print(f"泄漏的资源数量: {leaked_count}")
import json
import yaml
from pathlib import Path
class ConfigManager:
def __init__(self, config_file):
self.config_file = Path(config_file)
self.config = {}
def __enter__(self):
if self.config_file.exists():
with open(self.config_file, 'r', encoding='utf-8') as f:
if self.config_file.suffix.lower() == '.json':
self.config = json.load(f)
elif self.config_file.suffix.lower() in ['.yml', '.yaml']:
self.config = yaml.safe_load(f)
return self
def __exit__(self, exc_type, exc_value, traceback):
if exc_type is None: # 只有在没有异常时才保存
with open(self.config_file, 'w', encoding='utf-8') as f:
if self.config_file.suffix.lower() == '.json':
json.dump(self.config, f, indent=2, ensure_ascii=False)
elif self.config_file.suffix.lower() in ['.yml', '.yaml']:
yaml.dump(self.config, f, default_flow_style=False)
def get(self, key, default=None):
return self.config.get(key, default)
def set(self, key, value):
self.config[key] = value
# 使用配置管理器
with ConfigManager('app_config.json') as config:
config.set('database_url', 'postgresql://localhost/mydb')
config.set('debug', True)
db_url = config.get('database_url')
print(f"数据库URL: {db_url}")
import datetime
from contextlib import contextmanager
@contextmanager
def log_session(session_name, log_file='app.log'):
timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# 记录会话开始
with open(log_file, 'a', encoding='utf-8') as f:
f.write(f"[{timestamp}] 开始会话: {session_name}n")
try:
yield
except Exception as e:
# 记录异常
error_timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
with open(log_file, 'a', encoding='utf-8') as f:
f.write(f"[{error_timestamp}] 异常: {type(e).__name__}: {e}n")
raise
finally:
# 记录会话结束
end_timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
with open(log_file, 'a', encoding='utf-8') as f:
f.write(f"[{end_timestamp}] 结束会话: {session_name}n")
# 使用日志会话
with log_session("数据处理任务"):
print("开始处理数据...")
# 模拟一些工作
time.sleep(1)
print("数据处理完成")
# 如果需要测试异常处理,取消下面这行的注释
# raise ValueError("模拟异常")
from functools import wraps
from contextlib import contextmanager
@contextmanager
def performance_monitor(operation_name):
import time
start_time = time.time()
print(f"开始执行: {operation_name}")
try:
yield
finally:
end_time = time.time()
print(f"{operation_name} 完成,耗时: {end_time - start_time:.2f} 秒")
def monitored(func):
@wraps(func)
def wrapper(*args, **kwargs):
with performance_monitor(func.__name__):
return func(*args, **kwargs)
return wrapper
@monitored
def slow_function():
time.sleep(1)
return "完成"
result = slow_function()
def file_line_generator(filename):
"""逐行读取文件的生成器"""
with open(filename, 'r', encoding='utf-8') as f:
for line_number, line in enumerate(f, 1):
yield line_number, line.strip()
# 使用生成器处理大文件
def process_large_file_with_generator(filename):
line_count = 0
word_count = 0
for line_num, line in file_line_generator(filename):
line_count += 1
word_count += len(line.split())
if line_num % 1000 == 0:
print(f"已处理 {line_num} 行")
return line_count, word_count
# 创建测试文件
test_lines = [f"这是第{i}行,包含一些测试数据n" for i in range(1, 10001)]
with open('large_test.txt', 'w', encoding='utf-8') as f:
f.writelines(test_lines)
# 处理大文件
lines, words = process_large_file_with_generator('large_test.txt')
print(f"总行数: {lines}, 总词数: {words}")
# 不推荐:过多嵌套
with open('input.txt', 'r') as infile:
with open('output.txt', 'w') as outfile:
with open('log.txt', 'a') as logfile:
# 处理逻辑
pass
# 推荐:在同一行声明多个上下文管理器
with open('input.txt', 'r') as infile,
open('output.txt', 'w') as outfile,
open('log.txt', 'a') as logfile:
# 处理逻辑
pass
# 或者使用contextlib.ExitStack
from contextlib import ExitStack
def process_with_exit_stack():
with ExitStack() as stack:
infile = stack.enter_context(open('input.txt', 'r'))
outfile = stack.enter_context(open('output.txt', 'w'))
logfile = stack.enter_context(open('log.txt', 'a'))
# 处理逻辑
pass
from contextlib import nullcontext
def conditional_file_operation(use_log=True):
# 根据条件选择上下文管理器
log_context = open('operation.log', 'a') if use_log else nullcontext()
with log_context as log_file:
print("执行操作...")
if log_file:
log_file.write("操作执行成功n")
conditional_file_operation(True)
conditional_file_operation(False)
import pandas as pd
from contextlib import contextmanager
@contextmanager
def csv_processing_context(csv_file, output_file):
"""CSV处理上下文管理器"""
print(f"开始处理CSV文件: {csv_file}")
# 读取数据
df = pd.read_csv(csv_file)
original_shape = df.shape
try:
yield df
finally:
# 保存处理后的数据
df.to_csv(output_file, index=False)
print(f"处理完成,原数据形状: {original_shape},新数据形状: {df.shape}")
# 使用示例
# 创建测试数据
test_data = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'age': [25, 30, 35],
'city': ['New York', 'London', 'Tokyo']
})
test_data.to_csv('test_input.csv', index=False)
# 处理CSV文件
# with csv_processing_context('test_input.csv', 'test_output.csv') as df:
# df['age_group'] = df['age'].apply(lambda x: 'Young' if x < 30 else 'Adult')
# print(df.head())
# 假设使用sqlite3数据库
import sqlite3
from contextlib import contextmanager
@contextmanager
def database_transaction(db_path):
"""数据库事务上下文管理器"""
conn = sqlite3.connect(db_path)
try:
yield conn
conn.commit() # 提交事务
print("事务提交成功")
except Exception as e:
conn.rollback() # 回滚事务
print(f"事务回滚: {e}")
raise
finally:
conn.close()
# 使用数据库事务
# with database_transaction('example.db') as conn:
# cursor = conn.cursor()
# cursor.execute('''CREATE TABLE IF NOT EXISTS users
# (id INTEGER PRIMARY KEY, name TEXT, email TEXT)''')
# cursor.execute("INSERT INTO users (name, email) VALUES (?, ?)",
# ("张三", "zhangsan@example.com"))
from unittest.mock import patch, MagicMock
def test_with_statement():
"""测试with语句的行为"""
mock_file = MagicMock()
mock_file.__enter__.return_value = mock_file
mock_file.__exit__.return_value = None
with patch('builtins.open', return_value=mock_file):
with open('test.txt', 'r') as f:
f.read()
# 验证文件方法被正确调用
mock_file.__enter__.assert_called_once()
mock_file.read.assert_called_once()
mock_file.__exit__.assert_called_once()
# 运行测试
test_with_statement()
print("测试通过 ✅")
import traceback
from contextlib import contextmanager
@contextmanager
def debug_context(name):
"""调试用的上下文管理器"""
print(f"进入上下文: {name}")
print(f"调用栈:")
for frame_info in traceback.extract_stack()[:-1]:
print(f" {frame_info.filename}:{frame_info.lineno} in {frame_info.name}")
try:
yield
except Exception as e:
print(f"在上下文 {name} 中捕获异常: {type(e).__name__}: {e}")
raise
finally:
print(f"退出上下文: {name}")
# 使用调试上下文
with debug_context("主程序"):
print("执行主要逻辑")
with debug_context("子任务"):
print("执行子任务")
# raise ValueError("测试异常") # 取消注释测试异常处理
from contextlib import ExitStack
def batch_file_operations(filenames, operation='read'):
"""批量文件操作优化"""
results = []
with ExitStack() as stack:
files = []
# 打开所有文件
for filename in filenames:
if operation == 'read':
file_obj = stack.enter_context(open(filename, 'r', encoding='utf-8'))
else:
file_obj = stack.enter_context(open(filename, 'w', encoding='utf-8'))
files.append((filename, file_obj))
# 执行操作
for filename, file_obj in files:
if operation == 'read':
content = file_obj.read()
results.append((filename, len(content)))
else:
file_obj.write(f"处理文件: {filename}n")
return results
# 创建测试文件
for i in range(5):
with open(f'test_{i}.txt', 'w', encoding='utf-8') as f:
f.write(f"这是测试文件 {i} 的内容n" * 10)
# 批量读取文件
results = batch_file_operations([f'test_{i}.txt' for i in range(5)], 'read')
for filename, size in results:
print(f"{filename}: {size} 字符")
import mmap
class MappedFileManager:
def __init__(self, filename, mode='r'):
self.filename = filename
self.mode = mode
self.file = None
self.mmap_obj = None
def __enter__(self):
# 打开文件
self.file = open(self.filename, 'r+b' if 'w' in self.mode else 'rb')
# 创建内存映射
self.mmap_obj = mmap.mmap(
self.file.fileno(),
0,
access=mmap.ACCESS_WRITE if 'w' in self.mode else mmap.ACCESS_READ
)
return self.mmap_obj
def __exit__(self, exc_type, exc_value, traceback):
if self.mmap_obj:
self.mmap_obj.close()
if self.file:
self.file.close()
# 使用内存映射文件
# with MappedFileManager('large_file.bin', 'w') as mm:
# mm.write(b'Hello, Memory-Mapped World!')
import os
from contextlib import contextmanager
@contextmanager
def secure_file_access(filename, mode='r'):
"""安全的文件访问上下文管理器"""
# 检查文件是否存在
if 'w' in mode and os.path.exists(filename):
# 检查写权限
if not os.access(filename, os.W_OK):
raise PermissionError(f"没有写入权限: {filename}")
elif 'r' in mode:
# 检查读权限
if not os.access(filename, os.R_OK):
raise PermissionError(f"没有读取权限: {filename}")
# 检查路径遍历攻击
if '..' in filename:
raise ValueError("不允许相对路径访问")
with open(filename, mode, encoding='utf-8') as f:
yield f
# 安全文件访问示例
try:
with secure_file_access('safe_file.txt', 'w') as f:
f.write('安全的内容')
print("文件写入成功")
except PermissionError as e:
print(f"权限错误: {e}")
except ValueError as e:
print(f"安全错误: {e}")
import tempfile
import os
from contextlib import contextmanager
@contextmanager
def secure_temp_file(suffix='', prefix='tmp'):
"""安全的临时文件管理器"""
temp_file = None
try:
# 创建临时文件
temp_file = tempfile.NamedTemporaryFile(
suffix=suffix,
prefix=prefix,
delete=False
)
temp_filename = temp_file.name
temp_file.close()
# 设置安全权限
os.chmod(temp_filename, 0o600) # 只有所有者可读写
yield temp_filename
finally:
# 确保临时文件被删除
if temp_file and os.path.exists(temp_file.name):
os.unlink(temp_file.name)
# 使用安全临时文件
with secure_temp_file('.txt', 'myapp_') as temp_file:
with open(temp_file, 'w') as f:
f.write('临时数据')
print(f"临时文件路径: {temp_file}")
# 文件在这里会被自动删除
from typing import ContextManager, TextIO
from contextlib import contextmanager
@contextmanager
def typed_file_manager(filename: str, mode: str = 'r') -> ContextManager[TextIO]:
"""带类型提示的文件管理器"""
with open(filename, mode, encoding='utf-8') as f:
yield f
# 使用带类型的上下文管理器
with typed_file_manager('example.txt', 'w') as f:
f.write('类型安全的文件操作')
import asyncio
from typing import AsyncContextManager
from contextlib import asynccontextmanager
@asynccontextmanager
async def async_file_manager(filename: str, mode: str = 'r') -> AsyncContextManager:
"""异步文件管理器"""
loop = asyncio.get_event_loop()
# 在线程池中执行阻塞的文件操作
file_obj = await loop.run_in_executor(None, open, filename, mode)
try:
yield file_obj
finally:
await loop.run_in_executor(None, file_obj.close)
# 使用异步上下文管理器
async def async_file_operation():
async with async_file_manager('async_example.txt', 'w') as f:
await asyncio.get_event_loop().run_in_executor(None, f.write, '异步文件内容')
# 运行异步函数
# asyncio.run(async_file_operation())
with语句是Python管理资源的核心机制,它不仅让代码更简洁,也大大提高了程序的健壮性和可靠性。下面是一些经过实践检验的最佳做法:
close()的方式了,让上下文管理器替你操心。encoding参数指定字符集,避免跨平台时出现乱码。try-except包裹,优雅地应对文件不存在、权限不足等状况。@contextmanager、suppress、ExitStack等工具能帮你省下大量代码。掌握了这些技巧,你写出来的代码会健壮得多、也容易维护得多。说到底,资源管理不只是技术细节,更是专业素养的体现。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8