核心概念:模块
在 Python 中,每一个 .py 文件都可以被称为一个 模块,当你导入一个文件时,你实际上是在导入它的模块。

假设你有以下两个文件,它们位于同一个文件夹 my_project 中:
文件结构:
my_project/
├── my_module.py # 这是我们要导入的模块文件
└── main_script.py # 这是我们要运行的主脚本文件
导入同一目录下的模块
这是最常见、最简单的情况。
my_module.py (被导入的文件)
这个文件包含一些可以被其他文件使用的代码,比如变量、函数或类。

# my_module.py
# 定义一个变量
MODULE_CONSTANT = "Hello from my_module!"
# 定义一个函数
def greet(name):
"""打印一个问候语"""
print(f"Welcome, {name}! This is a function from my_module.")
# 定义一个类
class Calculator:
def add(self, a, b):
return a + b
main_script.py (执行导入的文件)
这个文件会导入并使用 my_module.py 中的内容。
方法 A:导入整个模块
使用 import module_name 语句。
# main_script.py
# 导入整个 my_module 模块
import my_module
# --- 使用模块中的内容 ---
# 1. 访问模块中的变量
print(my_module.MODULE_CONSTANT)
# 2. 调用模块中的函数
my_module.greet("Alice")
# 3. 使用模块中的类
calc = my_module.Calculator()
result = calc.add(10, 5)
print(f"The result of the calculation is: {result}")
如何运行:
打开终端或命令行,进入到 my_project 目录,然后运行:

python main_script.py
输出:
Hello from my_module!
Welcome, Alice! This is a function from my_module.
The result of the calculation is: 15
方法 B:导入特定成员
如果你只需要模块中的某个函数或变量,可以使用 from ... import ... 语句,这样就不需要每次都写模块名前缀。
# main_script_v2.py
# 从 my_module 中只导入 greet 函数和 MODULE_CONSTANT 变量
from my_module import greet, MODULE_CONSTANT
# --- 直接使用导入的成员,无需模块名前缀 ---
print(MODULE_CONSTANT)
greet("Bob")
# 如果尝试使用 Calculator,会报错 NameError,因为我们没有导入它
# calc = Calculator()
方法 C:导入所有成员
使用 from ... import * 会导入模块中所有不以下划线 _ 开头的公共成员。
# main_script_v3.py
# 导入 my_module 中的所有公共成员
from my_module import *
print(MODULE_CONSTANT)
greet("Charlie")
calc = Calculator()
print(calc.multiply(4, 3)) # 假设 my_module.py 中有 multiply 方法
⚠️ *`import 的警告**: 虽然import *` 看起来很方便,但它通常被认为是不好的实践,原因如下:
- 命名空间污染:它会把所有导入的名称都扔到当前文件的全局命名空间中,容易与你自己定义的变量或函数发生冲突。
- 代码可读性差:当别人(或未来的你)阅读代码时,很难快速知道某个变量或函数是从哪里来的。
- 难以维护:
my_module.py更新了,增加了新的公共成员,你的代码可能会在不知不觉中受到意想不到的影响。
最佳实践:优先使用 import module 或 from module import specific_item,尽量避免使用 import *。
导入不同目录下的模块
当你的项目变大,模块会分布在不同的文件夹中,这时就需要稍微复杂一点的导入方式。
项目结构调整
让我们把项目结构调整一下,增加一个 utils 文件夹。
my_project/
├── main_script.py
└── utils/
├── __init__.py # !!!关键文件
└── string_utils.py # 存放字符串相关工具的模块
关键点:要让 Python 将一个文件夹识别为一个 包,这个文件夹中必须包含一个名为 __init__.py 的文件,这个文件可以为空,它的作用是告诉 Python “这个目录是一个 Python 包”。
utils/string_utils.py (子目录下的模块)
# utils/string_utils.py
def reverse_string(text):
"""反转一个字符串"""
return text[::-1]
def capitalize_words(text):
"""将字符串中的每个单词首字母大写"""
return ' '.join(word.capitalize() for word in text.split())
main_script.py (导入子目录下的模块)
我们从 main_script.py 导入 utils 包中的 string_utils。
# main_script.py
# 方法 A: 导入整个包,然后使用包名.模块名 访问
import utils.string_utils
reversed_text = utils.string_utils.reverse_string("Python is fun")
print(f"Reversed text: {reversed_text}")
# 方法 B: 从包中导入特定的模块
from utils import string_utils
capitalized_text = string_utils.capitalize_words("hello world of python")
print(f"Capitalized text: {capitalized_text}")
# 方法 C: 从模块中导入特定的函数 (推荐)
from utils.string_utils import reverse_string, capitalize_words
# 现在可以直接使用函数了
print(f"Directly using function: {reverse_string('direct call')}")
导入项目根目录外的模块
你可能想导入一个不在项目当前目录或子目录中的模块,你有一个共享的工具库 shared_lib 在项目之外。
/path/to/my_project/
└── main_script.py
/path/to/shared_lib/
└── helper.py
helper.py 的内容:
# /path/to/shared_lib/helper.py
def do_something():
print("Doing something from the shared library!")
main_script.py 的内容:
# /path/to/my_project/main_script.py # 直接导入会失败: ModuleNotFoundError: No module named 'shared_lib' # import shared_lib.helper # 解决方案:将共享库的父目录添加到 sys.path import sys import os # 获取 shared_lib 的绝对路径 # 假设 main_script.py 在 /path/to/my_project/ # shared_lib 在 /path/to/shared_lib/ # 那么我们需要添加的路径是 /path/to/ project_root = os.path.dirname(os.path.abspath(__file__)) shared_lib_parent_dir = os.path.dirname(project_root) # 向上两级到 /path/to/ # 将路径添加到 sys.path sys.path.append(shared_lib_parent_dir) # 现在可以成功导入了 from shared_lib import helper helper.do_something()
更优雅的解决方案(推荐):
对于大型项目,强烈建议使用 虚拟环境 和 包管理工具(如 pip),你可以将 shared_lib 打包成一个标准的 Python 包(使用 setup.py),然后通过 pip install . 将其安装到你的 Python 环境中,之后,你就可以像导入任何第三方库(如 requests, numpy)一样直接导入了,无需修改 sys.path。
总结与最佳实践
| 场景 | 示例 | 说明 |
|---|---|---|
| 同一目录 | import my_modulefrom my_module import my_func |
最基本、最常用。 |
| 子目录 (包) | import utils.string_utilsfrom utils import string_utils |
子目录必须有 __init__.py 文件才能成为包。 |
| 项目外部 | sys.path.append('/path/to/module_parent')from my_module import my_func |
临时解决方案,不推荐用于大型项目。 |
| 第三方库 | import requests |
通过 pip install 安装后,直接导入即可。 |
核心原则:
- 明确性:代码应该清晰地表明它的依赖关系。
import module和from module import specific_item比import *更好。 - 避免命名冲突:不要给模块、函数或变量起与标准库或第三方库相同的名字(不要创建一个名为
os.py的文件)。 - 组织代码:将相关的功能组织到同一个模块(
.py文件)中,将相关的模块组织到同一个包(文件夹)中,使项目结构清晰。 - 使用虚拟环境:为每个项目创建独立的虚拟环境,可以避免不同项目之间的包版本冲突,并简化依赖管理。
