Python核心模块实战:时间处理、随机数与系统交互
1. Python常用模块深度解析与应用实战
作为Python开发者,我们每天都在与各种内置模块打交道。这些模块就像是Python标准库中的瑞士军刀,能帮我们高效处理各种常见任务。今天我将结合自己多年的开发经验,带大家深入剖析time、datetime、random、os、sys等核心模块的实用技巧和底层原理。
1.1 时间处理:time与datetime模块
1.1.1 time模块的三种时间表示形式
time模块提供了三种主要的时间表示方式,理解它们的区别是高效处理时间的基础:
-
时间戳(Timestamp) :从1970年1月1日00:00:00开始计算的秒数(浮点数)
import time current_timestamp = time.time() # 例如:1712345678.123456 -
结构化时间(struct_time) :包含9个元素的元组,表示时间的各个组成部分
local_time = time.localtime() # 输出:time.struct_time(tm_year=2023, tm_mon=6, tm_mday=15, ...) -
格式化时间字符串 :人类可读的时间表示
formatted_time = time.strftime("%Y-%m-%d %H:%M:%S") # 输出:"2023-06-15 14:30:00"
经验之谈 :在存储时间数据时优先使用时间戳,因为它是UTC时间且计算方便;在显示给用户时转换为格式化字符串;在需要获取时间的各个组成部分时使用struct_time。
1.1.2 时间格式转换关系图
graph LR
A[时间戳] -->|localtime/gmtime| B[结构化时间]
B -->|strftime| C[格式化字符串]
C -->|strptime| B
B -->|mktime| A
1.1.3 datetime模块的高级用法
datetime模块在time基础上提供了更友好的面向对象接口:
from datetime import datetime, timedelta
# 获取当前时间
now = datetime.now()
# 时间加减
tomorrow = now + timedelta(days=1)
last_week = now - timedelta(weeks=1)
# 时间替换
new_time = now.replace(hour=8, minute=0)
# 时间差计算
time_diff = datetime(2023, 7, 1) - datetime(2023, 6, 1)
print(time_diff.days) # 输出30
实用技巧 :处理跨时区问题时,建议始终在内部使用UTC时间,只在显示时转换为本地时间:
from datetime import timezone
utc_time = datetime.now(timezone.utc)
local_time = utc_time.astimezone()
2. 随机数生成与系统交互
2.1 random模块的妙用
random模块不仅能生成随机数,还能解决很多实际问题:
import random
import string
# 生成随机验证码
def generate_verification_code(length=6):
chars = string.ascii_letters + string.digits
return ''.join(random.choice(chars) for _ in range(length))
# 加权随机选择
items = [('一等奖', 1), ('二等奖', 3), ('三等奖', 10)]
population, weights = zip(*items)
result = random.choices(population, weights=weights, k=1)[0]
常见陷阱 :random模块生成的是伪随机数,如果需要加密级别的随机数,应使用 secrets 模块:
import secrets
secure_token = secrets.token_hex(16) # 生成32字符的安全随机字符串
2.2 os与sys模块的系统级操作
这两个模块是与操作系统交互的利器:
import os
import sys
# 安全的文件路径操作
config_path = os.path.join(os.path.expanduser('~'), '.config', 'myapp')
os.makedirs(config_path, exist_ok=True) # Python 3.2+ 支持exist_ok参数
# 获取脚本所在目录
script_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
# 跨平台路径处理
data_file = os.path.join(script_dir, 'data', 'records.csv')
重要区别 :
os模块:主要处理文件和目录操作、环境变量等sys模块:处理Python解释器相关的操作,如命令行参数、模块搜索路径等
3. 文件操作与数据序列化
3.1 shutil模块的高级文件操作
shutil提供了比os更高级的文件操作功能:
import shutil
# 递归复制目录
shutil.copytree('source_dir', 'backup_dir',
ignore=shutil.ignore_patterns('*.tmp', '*.log'))
# 磁盘空间检查
total, used, free = shutil.disk_usage('/')
if free < 1e9: # 小于1GB空间
print("磁盘空间不足!")
3.2 数据序列化:json与pickle的比较
| 特性 | json模块 | pickle模块 |
|---|---|---|
| 数据格式 | 文本(UTF-8) | 二进制 |
| 安全性 | 安全 | 可能执行任意代码 |
| 跨语言 | 支持 | 仅Python |
| 数据类型 | 基本数据类型 | 几乎所有Python对象 |
| 速度 | 较慢 | 较快 |
最佳实践 :
- 需要与其他语言交互或存储配置时用json
- 仅Python环境且需要保存复杂对象时用pickle
import json
import pickle
# json序列化
data = {'name': 'Alice', 'age': 25, 'scores': [88, 92, 95]}
json_str = json.dumps(data, indent=2)
# pickle序列化
with open('data.pkl', 'wb') as f:
pickle.dump(data, f, protocol=pickle.HIGHEST_PROTOCOL)
4. 配置处理与日志记录
4.1 配置文件解析:configparser与yaml
处理INI格式配置文件:
from configparser import ConfigParser
config = ConfigParser()
config.read('config.ini')
db_host = config.get('database', 'host', fallback='localhost')
db_port = config.getint('database', 'port', fallback=3306)
处理更复杂的YAML配置:
import yaml
with open('config.yaml') as f:
config = yaml.safe_load(f)
# 示例YAML内容:
# database:
# host: db.example.com
# port: 3306
# credentials:
# username: admin
# password: secret
4.2 强大的日志系统:logging模块
一个完整的日志配置示例:
import logging
from logging.handlers import RotatingFileHandler
def setup_logger(name):
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
# 控制台Handler
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
# 文件Handler(按大小轮转)
fh = RotatingFileHandler('app.log', maxBytes=10*1024*1024, backupCount=5)
fh.setLevel(logging.DEBUG)
# 格式化
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
fh.setFormatter(formatter)
logger.addHandler(ch)
logger.addHandler(fh)
return logger
# 使用示例
logger = setup_logger('myapp')
logger.info('系统启动')
try:
1 / 0
except Exception as e:
logger.error('发生错误', exc_info=True)
日志级别使用建议 :
- DEBUG:详细的调试信息
- INFO:正常的运行信息
- WARNING:潜在的问题
- ERROR:严重错误,但程序还能运行
- CRITICAL:致命错误,程序可能无法继续
5. 正则表达式高级技巧
5.1 re模块的核心方法
import re
# 编译正则表达式提高性能
pattern = re.compile(r'(\d{3})-(\d{3})-(\d{4})')
# 多种匹配方式
if pattern.match('123-456-7890'): # 从开头匹配
print("有效电话号码")
# 搜索所有匹配
text = "联系我:123-456-7890 或 987-654-3210"
for match in pattern.finditer(text):
print(f"找到电话号码:{match.group()}")
5.2 常用正则表达式模式
| 需求 | 正则表达式 | 说明 |
|---|---|---|
| 邮箱地址 | r'[\w.-]+@[\w.-]+\.\w+' |
匹配简单邮箱格式 |
| URL | r'https?://[\w.-]+\.\w+' |
匹配HTTP/HTTPS网址 |
| HTML标签 | r'<([a-z][a-z0-9]*)[^>]*>' |
匹配开始标签 |
| 中文文本 | r'[\u4e00-\u9fa5]+' |
匹配中文字符 |
| 强密码验证 | r'^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$' |
至少8位,含大小写和数字 |
性能优化建议 :
- 对频繁使用的正则表达式进行预编译
- 尽量使用非贪婪匹配(
.*?)避免回溯问题 - 复杂的正则表达式可以拆分为多个简单表达式
- 使用
re.VERBOSE标志提高可读性:
pattern = re.compile(r"""
^\s* # 开头可能有空格
([a-z0-9_.+-]+) # 用户名部分
@ # @符号
([a-z0-9-]+\.)+ # 域名前缀
([a-z]{2,}) # 顶级域名
\s*$ # 结尾可能有空格
""", re.VERBOSE | re.IGNORECASE)
6. 模块使用中的常见问题与解决方案
6.1 时区处理问题
问题现象 :跨时区应用中出现时间不一致
解决方案 :
from datetime import datetime, timezone
import pytz # 需要安装pytz包
# 创建带时区的时间
utc_time = datetime.now(timezone.utc)
beijing_time = utc_time.astimezone(pytz.timezone('Asia/Shanghai'))
# 时区转换
new_york_time = beijing_time.astimezone(pytz.timezone('America/New_York'))
6.2 文件路径跨平台兼容性
问题现象 :在Windows和Linux上路径分隔符不一致
解决方案 :
import os
# 正确方式
config_path = os.path.join('config', 'app', 'settings.ini')
# 错误方式(Windows不兼容)
bad_path = 'config/app/settings.ini'
6.3 pickle安全风险
问题现象 :反序列化不可信数据导致代码执行
解决方案 :
import pickle
# 安全做法:使用更安全的替代方案
def safe_load(pickle_file):
with open(pickle_file, 'rb') as f:
return pickle.load(f) # 仅加载可信来源的数据
# 或者使用更安全的json模块
6.4 日志文件轮转策略
问题现象 :日志文件无限增长占用磁盘空间
解决方案 :
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
# 按大小轮转(每个文件最大10MB,保留5个备份)
size_handler = RotatingFileHandler('app.log', maxBytes=10*1024*1024, backupCount=5)
# 按时间轮转(每天午夜轮转,保留7天)
time_handler = TimedRotatingFileHandler('app.log', when='midnight', backupCount=7)
7. 综合应用案例:自动化备份脚本
结合多个模块的实际应用示例:
#!/usr/bin/env python3
import os
import sys
import time
import shutil
import logging
from datetime import datetime
def setup_logging():
"""配置日志系统"""
logger = logging.getLogger('backup_tool')
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
# 控制台输出
console = logging.StreamHandler()
console.setFormatter(formatter)
logger.addHandler(console)
# 文件输出
file_handler = logging.FileHandler('backup.log')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
return logger
def create_backup(source, dest_dir):
"""创建备份"""
logger = logging.getLogger('backup_tool')
if not os.path.exists(source):
logger.error(f"源目录不存在: {source}")
return False
# 创建带时间戳的备份目录
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
backup_name = f"backup_{timestamp}"
backup_path = os.path.join(dest_dir, backup_name)
try:
logger.info(f"开始备份 {source} 到 {backup_path}")
shutil.copytree(source, backup_path)
logger.info("备份成功完成")
return True
except Exception as e:
logger.error(f"备份失败: {str(e)}", exc_info=True)
return False
def main():
if len(sys.argv) != 3:
print(f"用法: {sys.argv[0]} <源目录> <目标目录>")
sys.exit(1)
logger = setup_logging()
source = os.path.abspath(sys.argv[1])
dest = os.path.abspath(sys.argv[2])
logger.info(f"启动备份程序,源: {source}, 目标: {dest}")
start_time = time.time()
if create_backup(source, dest):
elapsed = time.time() - start_time
logger.info(f"备份完成,耗时: {elapsed:.2f}秒")
else:
logger.warning("备份过程中出现错误")
if __name__ == '__main__':
main()
这个脚本展示了如何综合运用多个模块:
os和sys处理文件和命令行参数time和datetime处理时间相关操作shutil执行文件操作logging记录操作日志
8. 性能优化与最佳实践
8.1 模块导入优化
不良实践 :
import os, sys, time, datetime # 一行导入多个模块
from module import * # 通配符导入
推荐做法 :
# 分组导入,标准库在前
import os
import sys
import time
from datetime import datetime # 只导入需要的部分
# 第三方库
import requests
import numpy as np
# 本地模块
from . import utils
8.2 避免重复计算
对于频繁使用的模块属性,可以缓存到局部变量:
# 不佳的方式
for i in range(10000):
value = math.sqrt(i) * math.sin(i)
# 更好的方式
sqrt = math.sqrt
sin = math.sin
for i in range(10000):
value = sqrt(i) * sin(i)
8.3 使用生成器处理大数据
当处理大量数据时,使用生成器可以节省内存:
import os
# 不佳的方式(加载所有文件到内存)
def get_all_files(path):
return [f for f in os.listdir(path) if os.path.isfile(f)]
# 更好的方式(生成器)
def iter_files(path):
for f in os.listdir(path):
if os.path.isfile(f):
yield f
9. 模块的替代方案与扩展
虽然Python标准库很强大,但有时第三方库能提供更好的解决方案:
| 标准模块 | 第三方替代方案 | 优势 |
|---|---|---|
| datetime | arrow, pendulum | 更友好的API,更好的时区支持 |
| json | orjson, ujson | 更快的性能 |
| random | numpy.random | 更专业的随机数生成 |
| re | regex | 支持更多正则特性 |
| os.path | pathlib | 面向对象的路径操作 |
例如,使用 pathlib 替代 os.path :
from pathlib import Path
# 创建目录
config_dir = Path.home() / '.config' / 'myapp'
config_dir.mkdir(parents=True, exist_ok=True)
# 读取文件内容
config_file = config_dir / 'settings.ini'
if config_file.exists():
content = config_file.read_text(encoding='utf-8')
10. 调试与性能分析技巧
10.1 使用timeit测量代码执行时间
import timeit
# 测量代码片段执行时间
time = timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
print(f"执行时间: {time:.3f}秒")
10.2 使用cProfile进行性能分析
import cProfile
def slow_function():
total = 0
for i in range(10000):
for j in range(10000):
total += i * j
return total
# 性能分析
cProfile.run('slow_function()', sort='cumtime')
10.3 日志调试技巧
在开发阶段可以临时提高日志级别:
import logging
logging.basicConfig(level=logging.DEBUG) # 开发时设置为DEBUG
logger = logging.getLogger(__name__)
# 在关键位置添加调试日志
logger.debug("变量值: %r", some_var)
日志级别建议 :
- 开发环境:DEBUG
- 测试环境:INFO
- 生产环境:WARNING或ERROR
11. 安全注意事项
11.1 处理用户输入时的安全风险
import os
# 危险的做法
user_input = input("请输入文件名: ")
file_path = os.path.join('/data', user_input) # 可能包含路径遍历攻击
# 安全的做法
from pathlib import Path
user_input = input("请输入文件名: ")
try:
file_path = Path('/data') / Path(user_input).name # 只取文件名部分
if not file_path.resolve().is_relative_to(Path('/data')):
raise ValueError("非法路径")
except ValueError as e:
print(f"错误: {e}")
11.2 安全地执行系统命令
避免直接使用 os.system :
import subprocess
# 危险的做法
filename = input("输入文件名: ")
os.system(f"rm {filename}") # 命令注入风险
# 安全的做法
try:
subprocess.run(['rm', filename], check=True)
except subprocess.CalledProcessError as e:
print(f"命令执行失败: {e}")
11.3 敏感信息处理
不要在日志中记录敏感信息:
import logging
# 不好的做法
logging.info(f"用户登录,用户名: {username}, 密码: {password}")
# 好的做法
logging.info(f"用户登录,用户名: {username[:3]}***")
12. 模块的进阶用法
12.1 动态导入模块
import importlib
def load_module(module_name):
try:
module = importlib.import_module(module_name)
print(f"成功加载模块: {module.__name__}")
return module
except ImportError as e:
print(f"无法加载模块 {module_name}: {e}")
return None
# 使用示例
plugin = load_module('my_plugin')
if plugin:
plugin.run()
12.2 创建自定义模块
一个完整的模块示例(保存为 mymodule.py ):
"""这是一个自定义模块的示例"""
import logging
from datetime import datetime
__version__ = '1.0.0'
logger = logging.getLogger(__name__)
class MyClass:
"""示例类"""
def __init__(self, name):
self.name = name
self.created_at = datetime.now()
def greet(self):
"""打招呼方法"""
logger.info(f"来自 {self.name} 的问候")
return f"Hello, {self.name}! 创建于 {self.created_at:%Y-%m-%d}"
def utility_function(data):
"""实用函数示例"""
if not data:
logger.warning("接收到空数据")
return None
return data.upper()
if __name__ == '__main__':
# 模块自测试代码
logging.basicConfig(level=logging.INFO)
obj = MyClass("测试")
print(obj.greet())
12.3 使用__all__控制导入
在模块中定义 __all__ 可以控制 from module import * 的行为:
# 在mymodule.py中
__all__ = ['MyClass', 'utility_function'] # 只导出这两个名称
# 这样from mymodule import * 时只会导入这两个名称
13. 跨平台开发注意事项
13.1 路径分隔符处理
import os
# 不好的做法(Windows不兼容)
path = 'data/files/image.jpg'
# 好的做法
path = os.path.join('data', 'files', 'image.jpg')
# 更好的做法(Python 3.4+)
from pathlib import Path
path = Path('data') / 'files' / 'image.jpg'
13.2 行结束符处理
# 读取文本文件时统一处理行结束符
with open('data.txt', 'r', newline='') as f:
content = f.read() # 自动处理不同平台的换行符
13.3 平台特定代码
import sys
if sys.platform == 'win32':
# Windows特定代码
config_path = os.path.join(os.environ['APPDATA'], 'myapp')
elif sys.platform == 'darwin':
# MacOS特定代码
config_path = os.path.join(os.path.expanduser('~'), 'Library', 'Application Support', 'myapp')
else:
# Linux/Unix
config_path = os.path.join(os.path.expanduser('~'), '.config', 'myapp')
14. 测试与质量保证
14.1 为模块编写单元测试
使用 unittest 模块测试自定义模块:
import unittest
import mymodule
class TestMyModule(unittest.TestCase):
def setUp(self):
self.obj = mymodule.MyClass("测试")
def test_greet(self):
result = self.obj.greet()
self.assertIn("测试", result)
def test_utility_function(self):
self.assertEqual(mymodule.utility_function("abc"), "ABC")
self.assertIsNone(mymodule.utility_function(None))
if __name__ == '__main__':
unittest.main()
14.2 使用mock进行测试
from unittest.mock import patch
import mymodule
class TestWithMock(unittest.TestCase):
@patch('mymodule.logging')
def test_logging(self, mock_logging):
obj = mymodule.MyClass("mock测试")
obj.greet()
mock_logging.info.assert_called_with("来自 mock测试 的问候")
14.3 性能测试
import timeit
def test_performance():
setup = 'from mymodule import utility_function'
stmt = 'utility_function("test_string")'
time = timeit.timeit(stmt, setup=setup, number=10000)
print(f"10000次调用耗时: {time:.3f}秒")
15. 模块打包与分发
15.1 基本项目结构
my_package/
├── my_package/ # 主包目录
│ ├── __init__.py # 包初始化文件
│ ├── core.py # 核心模块
│ └── utils.py # 工具模块
├── tests/ # 测试目录
│ ├── __init__.py
│ └── test_core.py
├── setup.py # 打包配置
├── README.md # 项目说明
└── requirements.txt # 依赖列表
15.2 setup.py示例
from setuptools import setup, find_packages
setup(
name="my_package",
version="0.1.0",
packages=find_packages(),
install_requires=[
'requests>=2.25.0',
],
extras_require={
'dev': [
'pytest>=6.0',
'black>=21.0',
],
},
python_requires='>=3.6',
)
15.3 构建与发布
# 安装构建工具
pip install setuptools wheel twine
# 构建分发包
python setup.py sdist bdist_wheel
# 检查构建结果
twine check dist/*
# 上传到PyPI
twine upload dist/*
16. 模块文档编写规范
良好的文档能让模块更易于使用:
16.1 模块级文档字符串
"""
mymodule - 一个示例模块
这个模块提供了XXX功能,主要包含以下内容:
- MyClass: 用于XXX的类
- utility_function: 提供YYY功能的工具函数
示例用法:
>>> from mymodule import MyClass
>>> obj = MyClass("测试")
>>> print(obj.greet())
"""
__version__ = '0.1.0'
__author__ = 'Your Name <your.email@example.com>'
16.2 类文档字符串
class MyClass:
"""一个示例类
这个类主要用于演示如何编写良好的文档字符串。
Attributes:
name (str): 实例名称
created_at (datetime): 实例创建时间
"""
def __init__(self, name):
"""初始化MyClass实例
Args:
name: 实例名称
"""
self.name = name
self.created_at = datetime.now()
16.3 函数文档字符串
def utility_function(data):
"""将输入数据转换为大写
这是一个示例函数,演示如何编写函数文档。
Args:
data (str): 输入字符串,如果为None则返回None
Returns:
str: 大写的输入字符串,或None
Raises:
TypeError: 如果输入不是字符串也不是None
Examples:
>>> utility_function("hello")
'HELLO'
>>> utility_function(None) is None
True
"""
if data is None:
return None
if not isinstance(data, str):
raise TypeError("输入必须是字符串")
return data.upper()
17. 模块设计原则
17.1 单一职责原则
每个模块应该只负责一个明确的功能领域。例如:
time_utils.py:处理时间相关功能file_utils.py:处理文件操作network_utils.py:处理网络请求
17.2 最小接口原则
只暴露必要的接口给外部使用:
# 在模块内部
def _internal_helper():
"""内部使用的辅助函数"""
pass
def public_api():
"""对外公开的API"""
_internal_helper()
return result
# 在__init__.py中控制导出
__all__ = ['public_api']
17.3 防御性编程
def safe_divide(a, b):
"""安全的除法运算
Args:
a: 被除数
b: 除数
Returns:
除法结果
Raises:
ValueError: 如果除数为0
TypeError: 如果输入不是数字
"""
if not isinstance(a, (int, float)) or not isinstance(b, (int, float)):
raise TypeError("输入必须是数字")
if b == 0:
raise ValueError("除数不能为0")
return a / b
18. 性能敏感场景的优化
18.1 避免在循环中导入模块
# 不好的做法
def process_items(items):
for item in items:
import json # 每次循环都导入
data = json.loads(item)
...
# 好的做法
import json # 在模块顶部导入
def process_items(items):
for item in items:
data = json.loads(item)
...
18.2 使用functools.lru_cache缓存结果
from functools import lru_cache
import os
@lru_cache(maxsize=128)
def get_file_info(path):
"""获取文件信息并缓存结果"""
return os.stat(path)
18.3 选择高效的数据结构
# 频繁成员检查使用集合而不是列表
valid_names = {'Alice', 'Bob', 'Charlie'} # 集合查找O(1)
# 而不是
valid_names = ['Alice', 'Bob', 'Charlie'] # 列表查找O(n)
19. 异步编程中的模块使用
19.1 asyncio与time模块
import asyncio
import time
async def task():
print("任务开始")
start = time.monotonic() # 使用monotonic避免时间调整影响
await asyncio.sleep(1)
duration = time.monotonic() - start
print(f"任务完成,耗时{duration:.2f}秒")
asyncio.run(task())
19.2 异步文件操作
import aiofiles # 需要安装aiofiles
async def async_write_file():
async with aiofiles.open('data.txt', mode='w') as f:
await f.write("异步写入内容")
asyncio.run(async_write_file())
19.3 异步HTTP请求
import aiohttp # 需要安装aiohttp
async def fetch_url(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
html = asyncio.run(fetch_url('https://example.com'))
20. 模块的未来发展与替代方案
20.1 新版本Python中的改进
Python 3.9+ 对模块系统的改进:
zoneinfo模块替代pytz处理时区graphlib新增拓扑排序功能importlib增强动态导入能力
20.2 值得关注的第三方库
- 日期时间:
pendulum、arrow - 日志:
loguru简化日志配置 - 配置文件:
python-decouple、dynaconf - 命令行:
click、typer替代argparse
20.3 模块的弃用与迁移
关注Python的弃用警告:
import warnings
def old_function():
warnings.warn(
"old_function已弃用,请使用new_function",
DeprecationWarning,
stacklevel=2
)
...
21. 模块的调试技巧
21.1 查看模块属性
import random
# 查看模块所有属性
print(dir(random))
# 查看特定属性帮助
help(random.randint)
21.2 重新加载模块
在交互式环境中开发时:
import importlib
import mymodule
# 修改mymodule后重新加载
importlib.reload(mymodule)
21.3 跟踪模块导入
import sys
import importlib.util
def trace_imports():
def trace_find_spec(name, path, target=None):
print(f"尝试导入: {name}")
return None
sys.meta_path.insert(0, type('TraceFinder', (), {'find_spec': trace_find_spec}))
trace_imports()
import os # 会打印导入信息
22. 模块资源管理
22.1 使用上下文管理器
import tempfile
import shutil
class TempDirectory:
def __enter__(self):
self.path = tempfile.mkdtemp()
return self.path
def __exit__(self, exc_type, exc_val, exc_tb):
shutil.rmtree(self.path)
# 使用示例
with TempDirectory() as temp_dir:
print(f"临时目录: {temp_dir}")
# 自动清理
22.2 资源清理模式
import atexit
def cleanup():
print("执行清理操作")
atexit.register(cleanup) # 程序退出时执行
22.3 使用weakref管理资源
import weakref
class Resource:
pass
# 创建资源
res = Resource()
# 弱引用不会阻止垃圾回收
weak_res = weakref.ref(res)
23. 模块的国际化与本地化
23.1 使用gettext模块
import gettext
# 设置本地化目录
locales_dir = 'locales'
lang = 'zh_CN'
# 配置翻译
translation = gettext.translation(
'myapp',
locales_dir,
languages=[lang],
fallback=True
)
translation.install()
# 使用
print(_("Hello, world!")) # 会根据语言环境显示不同翻译
23.2 处理多语言日期
from datetime import datetime
import locale
# 设置本地化环境
locale.setlocale(locale.LC_TIME, 'zh_CN.UTF-8')
# 格式化日期
now = datetime.now()
print(now.strftime("%A, %d %B %Y")) # 输出"星期一, 15 六月 2023"
23.3 数字和货币格式化
import locale
# 设置本地化环境
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
# 格式化货币
amount = 1234567.89
print(locale.currency(amount)) # 输出"$1,234,567.89"
24. 模块的线程安全考虑
24.1 线程安全的随机数生成
import random
import threading
# 每个线程有自己的随机数生成器状态
local_random = threading.local()
def get_random():
if not hasattr(local_random, 'rng'):
local_random.rng = random.Random()
return local_random.rng.randint(1, 100)
24.2 使用锁保护共享资源
import threading
from collections import defaultdict
# 共享数据结构
shared_data = defaultdict(int)
lock = threading.Lock()
def safe_increment(key):
with lock: # 确保线程安全
shared_data[key] += 1
24.3
更多推荐



所有评论(0)