Skip to content

Commit cd11e1c

Browse files
committed
feat(modules): 添加Python模块系统学习内容
docs: 更新模块相关文档和指南 feat: 添加模块基础、导入语句、搜索路径等核心文件 feat: 实现__name__变量和模块重载功能 docs: 完善模块文档系统和示例代码 style: 格式化模块相关代码和文档
1 parent b546199 commit cd11e1c

28 files changed

Lines changed: 13266 additions & 194 deletions

27-modules/01_module_basics.py

Lines changed: 535 additions & 0 deletions
Large diffs are not rendered by default.

27-modules/02_import_statements.py

Lines changed: 460 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 397 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,397 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
"""
4+
模块搜索路径演示
5+
6+
本文件演示Python如何搜索和定位模块,包括:
7+
1. sys.path的作用和内容
8+
2. 模块搜索顺序
9+
3. 动态修改搜索路径
10+
4. PYTHONPATH环境变量
11+
5. .pth文件的使用
12+
6. 包的搜索机制
13+
14+
学习目标:
15+
- 理解Python模块搜索机制
16+
- 掌握如何查看和修改搜索路径
17+
- 了解不同搜索路径的优先级
18+
- 学会解决模块导入问题
19+
"""
20+
21+
import sys
22+
import os
23+
from pathlib import Path
24+
25+
# ============================================================================
26+
# 1. 查看当前的模块搜索路径
27+
# ============================================================================
28+
29+
def show_current_search_paths():
30+
"""
31+
显示当前的模块搜索路径
32+
"""
33+
print("=== 1. 当前模块搜索路径 ===")
34+
print("Python在以下路径中按顺序搜索模块:\n")
35+
36+
for i, path in enumerate(sys.path, 1):
37+
print(f"{i:2d}. {path}")
38+
39+
# 检查路径是否存在
40+
if os.path.exists(path):
41+
path_type = "目录" if os.path.isdir(path) else "文件"
42+
print(f" └─ [{path_type}] 存在")
43+
else:
44+
print(f" └─ [不存在]")
45+
46+
print(f"\n总共 {len(sys.path)} 个搜索路径")
47+
48+
# ============================================================================
49+
# 2. 分析搜索路径的来源
50+
# ============================================================================
51+
52+
def analyze_path_sources():
53+
"""
54+
分析各个搜索路径的来源
55+
"""
56+
print("\n=== 2. 搜索路径来源分析 ===")
57+
58+
# 当前工作目录
59+
current_dir = os.getcwd()
60+
print(f"当前工作目录: {current_dir}")
61+
62+
# 脚本所在目录
63+
script_dir = os.path.dirname(os.path.abspath(__file__))
64+
print(f"脚本所在目录: {script_dir}")
65+
66+
# Python安装目录
67+
python_home = sys.prefix
68+
print(f"Python安装目录: {python_home}")
69+
70+
# 标准库目录
71+
stdlib_dir = os.path.dirname(os.__file__)
72+
print(f"标准库目录: {stdlib_dir}")
73+
74+
# site-packages目录
75+
import site
76+
site_packages = site.getsitepackages()
77+
print(f"site-packages目录: {site_packages}")
78+
79+
# PYTHONPATH环境变量
80+
pythonpath = os.environ.get('PYTHONPATH', '')
81+
if pythonpath:
82+
print(f"PYTHONPATH环境变量: {pythonpath}")
83+
else:
84+
print("PYTHONPATH环境变量: 未设置")
85+
86+
# ============================================================================
87+
# 3. 演示模块搜索顺序
88+
# ============================================================================
89+
90+
def demonstrate_search_order():
91+
"""
92+
演示模块搜索的优先级顺序
93+
"""
94+
print("\n=== 3. 模块搜索顺序 ===")
95+
96+
print("Python按以下顺序搜索模块:")
97+
print("1. 内置模块 (built-in modules)")
98+
print("2. 当前目录或脚本所在目录")
99+
print("3. PYTHONPATH环境变量指定的目录")
100+
print("4. Python标准库目录")
101+
print("5. site-packages目录")
102+
print("6. .pth文件指定的目录")
103+
104+
# 演示内置模块
105+
print("\n内置模块示例:")
106+
builtin_modules = sys.builtin_module_names
107+
print(f"内置模块数量: {len(builtin_modules)}")
108+
print(f"部分内置模块: {list(builtin_modules)[:10]}...")
109+
110+
# 检查特定模块的位置
111+
modules_to_check = ['os', 'sys', 'json', 'datetime']
112+
print("\n标准库模块位置:")
113+
for module_name in modules_to_check:
114+
try:
115+
module = __import__(module_name)
116+
if hasattr(module, '__file__') and module.__file__:
117+
print(f"{module_name:10s}: {module.__file__}")
118+
else:
119+
print(f"{module_name:10s}: [内置模块]")
120+
except ImportError:
121+
print(f"{module_name:10s}: [未找到]")
122+
123+
# ============================================================================
124+
# 4. 动态修改搜索路径
125+
# ============================================================================
126+
127+
def demonstrate_path_modification():
128+
"""
129+
演示如何动态修改模块搜索路径
130+
"""
131+
print("\n=== 4. 动态修改搜索路径 ===")
132+
133+
# 保存原始路径
134+
original_path = sys.path.copy()
135+
print(f"原始路径数量: {len(original_path)}")
136+
137+
# 添加新路径到开头(最高优先级)
138+
new_path = "/tmp/my_modules"
139+
sys.path.insert(0, new_path)
140+
print(f"\n在开头添加路径: {new_path}")
141+
print(f"新的第一个搜索路径: {sys.path[0]}")
142+
143+
# 添加路径到末尾(最低优先级)
144+
another_path = "/tmp/low_priority"
145+
sys.path.append(another_path)
146+
print(f"\n在末尾添加路径: {another_path}")
147+
print(f"当前路径数量: {len(sys.path)}")
148+
149+
# 移除添加的路径
150+
if new_path in sys.path:
151+
sys.path.remove(new_path)
152+
print(f"\n移除路径: {new_path}")
153+
154+
if another_path in sys.path:
155+
sys.path.remove(another_path)
156+
print(f"移除路径: {another_path}")
157+
158+
# 恢复原始路径
159+
sys.path = original_path
160+
print(f"\n恢复原始路径,当前数量: {len(sys.path)}")
161+
162+
# ============================================================================
163+
# 5. 创建和使用临时模块
164+
# ============================================================================
165+
166+
def create_temporary_module():
167+
"""
168+
创建临时模块来演示搜索路径
169+
"""
170+
print("\n=== 5. 创建临时模块演示 ===")
171+
172+
# 创建临时目录
173+
temp_dir = "/tmp/python_module_demo"
174+
os.makedirs(temp_dir, exist_ok=True)
175+
176+
# 创建临时模块文件
177+
module_content = '''#!/usr/bin/env python3
178+
# -*- coding: utf-8 -*-
179+
"""
180+
临时演示模块
181+
"""
182+
183+
TEMP_MODULE_NAME = "临时模块"
184+
TEMP_MODULE_VERSION = "1.0.0"
185+
186+
def temp_function():
187+
return "这是临时模块中的函数"
188+
189+
class TempClass:
190+
def __init__(self):
191+
self.name = "临时类"
192+
193+
def get_info(self):
194+
return f"我是{self.name}"
195+
'''
196+
197+
module_file = os.path.join(temp_dir, "temp_module.py")
198+
with open(module_file, 'w', encoding='utf-8') as f:
199+
f.write(module_content)
200+
201+
print(f"创建临时模块: {module_file}")
202+
203+
# 将临时目录添加到搜索路径
204+
if temp_dir not in sys.path:
205+
sys.path.insert(0, temp_dir)
206+
print(f"添加到搜索路径: {temp_dir}")
207+
208+
# 尝试导入临时模块
209+
try:
210+
import temp_module
211+
print(f"\n成功导入临时模块: {temp_module.TEMP_MODULE_NAME}")
212+
print(f"模块版本: {temp_module.TEMP_MODULE_VERSION}")
213+
print(f"调用函数: {temp_module.temp_function()}")
214+
215+
# 使用临时类
216+
temp_obj = temp_module.TempClass()
217+
print(f"使用临时类: {temp_obj.get_info()}")
218+
219+
# 显示模块文件位置
220+
print(f"模块文件位置: {temp_module.__file__}")
221+
222+
except ImportError as e:
223+
print(f"导入临时模块失败: {e}")
224+
225+
# 清理:移除搜索路径
226+
if temp_dir in sys.path:
227+
sys.path.remove(temp_dir)
228+
print(f"\n从搜索路径移除: {temp_dir}")
229+
230+
# 清理:删除临时文件
231+
try:
232+
os.remove(module_file)
233+
os.rmdir(temp_dir)
234+
print(f"清理临时文件: {module_file}")
235+
except OSError:
236+
print(f"清理临时文件时出错")
237+
238+
# ============================================================================
239+
# 6. 包的搜索机制
240+
# ============================================================================
241+
242+
def demonstrate_package_search():
243+
"""
244+
演示包的搜索机制
245+
"""
246+
print("\n=== 6. 包的搜索机制 ===")
247+
248+
print("包搜索规则:")
249+
print("1. 包必须是包含__init__.py文件的目录")
250+
print("2. 包的搜索遵循与模块相同的路径规则")
251+
print("3. 子包通过点号分隔的路径访问")
252+
print("4. 相对导入只能在包内部使用")
253+
254+
# 检查一些常见包的位置
255+
packages_to_check = [
256+
'json',
257+
'urllib',
258+
'xml',
259+
'email',
260+
'collections'
261+
]
262+
263+
print("\n常见包的位置:")
264+
for package_name in packages_to_check:
265+
try:
266+
package = __import__(package_name)
267+
if hasattr(package, '__path__'):
268+
print(f"{package_name:12s}: {package.__path__}")
269+
elif hasattr(package, '__file__'):
270+
print(f"{package_name:12s}: {package.__file__}")
271+
else:
272+
print(f"{package_name:12s}: [内置]")
273+
except ImportError:
274+
print(f"{package_name:12s}: [未找到]")
275+
276+
# ============================================================================
277+
# 7. 搜索路径问题诊断
278+
# ============================================================================
279+
280+
def diagnose_import_issues():
281+
"""
282+
诊断常见的导入问题
283+
"""
284+
print("\n=== 7. 导入问题诊断 ===")
285+
286+
print("常见导入问题及解决方案:")
287+
print("\n1. ModuleNotFoundError:")
288+
print(" - 检查模块名拼写")
289+
print(" - 确认模块在搜索路径中")
290+
print(" - 检查PYTHONPATH设置")
291+
292+
print("\n2. 相对导入问题:")
293+
print(" - 相对导入只能在包内使用")
294+
print(" - 使用绝对导入更安全")
295+
296+
print("\n3. 循环导入:")
297+
print(" - 重新设计模块结构")
298+
print(" - 使用延迟导入")
299+
300+
print("\n4. 路径问题:")
301+
print(" - 检查当前工作目录")
302+
print(" - 使用绝对路径")
303+
print(" - 正确设置PYTHONPATH")
304+
305+
# 提供诊断工具
306+
print("\n诊断工具函数:")
307+
308+
def find_module_path(module_name):
309+
"""查找模块的实际路径"""
310+
try:
311+
import importlib.util
312+
spec = importlib.util.find_spec(module_name)
313+
if spec:
314+
return spec.origin or spec.submodule_search_locations
315+
else:
316+
return None
317+
except ImportError:
318+
return None
319+
320+
# 测试诊断工具
321+
test_modules = ['os', 'sys', 'nonexistent_module']
322+
for module in test_modules:
323+
path = find_module_path(module)
324+
if path:
325+
print(f" {module}: {path}")
326+
else:
327+
print(f" {module}: [未找到]")
328+
329+
# ============================================================================
330+
# 8. 最佳实践建议
331+
# ============================================================================
332+
333+
def show_best_practices():
334+
"""
335+
显示模块搜索路径的最佳实践
336+
"""
337+
print("\n=== 8. 最佳实践建议 ===")
338+
339+
practices = [
340+
"1. 使用虚拟环境管理项目依赖",
341+
"2. 避免修改sys.path,除非绝对必要",
342+
"3. 使用相对于项目根目录的导入",
343+
"4. 在setup.py或pyproject.toml中声明依赖",
344+
"5. 使用绝对导入而不是相对导入",
345+
"6. 保持模块结构简单清晰",
346+
"7. 使用包来组织相关模块",
347+
"8. 避免在运行时动态修改搜索路径",
348+
"9. 使用importlib进行动态导入",
349+
"10. 定期清理不需要的模块和包"
350+
]
351+
352+
for practice in practices:
353+
print(f" {practice}")
354+
355+
print("\n推荐的项目结构:")
356+
print("""
357+
my_project/
358+
├── setup.py
359+
├── requirements.txt
360+
├── my_package/
361+
│ ├── __init__.py
362+
│ ├── module1.py
363+
│ └── subpackage/
364+
│ ├── __init__.py
365+
│ └── module2.py
366+
├── tests/
367+
│ └── test_module1.py
368+
└── docs/
369+
└── README.md
370+
""")
371+
372+
# ============================================================================
373+
# 主函数
374+
# ============================================================================
375+
376+
def main():
377+
"""
378+
主函数:演示所有模块搜索路径相关功能
379+
"""
380+
print("Python模块搜索路径演示")
381+
print("=" * 60)
382+
383+
show_current_search_paths()
384+
analyze_path_sources()
385+
demonstrate_search_order()
386+
demonstrate_path_modification()
387+
create_temporary_module()
388+
demonstrate_package_search()
389+
diagnose_import_issues()
390+
show_best_practices()
391+
392+
print("\n" + "=" * 60)
393+
print("模块搜索路径演示完成!")
394+
print("=" * 60)
395+
396+
if __name__ == "__main__":
397+
main()

0 commit comments

Comments
 (0)