下面我将详细介绍这几种方法,并提供清晰的示例和适用场景分析。

场景设定
我们假设有两个文件,它们都在同一个目录下:
main_script.py(我们将要执行这个文件)helper_module.py(这个文件包含了我们想要使用的代码)
helper_module.py (被调用的文件)
这个文件里定义了一些函数和变量。
# helper_module.py
# 一个简单的函数
def greet(name):
"""向某人问好"""
print(f"你好, {name}! 欢迎来自 helper_module.py 的问候。")
# 一个计算函数
def add(a, b):
"""返回两个数的和"""
return a + b
# 一个模块级别的变量
MODULE_VERSION = "1.0"
导入 (Import) - 最常用、最规范的方法
这是Python中最推荐、最规范的方式,它将目标文件作为一个模块导入到当前命名空间中,然后你就可以像使用普通库一样使用它的函数和变量。
核心思想: 将代码作为“模块”或“库”来使用。

如何操作:
在 main_script.py 中,使用 import 语句。
# main_script.py
# 方式1: 导入整个模块
import helper_module
# 使用模块名.函数名 的方式调用
helper_module.greet("小明")
# 使用模块名.变量名 的方式访问
print(f"helper_module 的版本是: {helper_module.MODULE_VERSION}")
# 方式2: 导入特定的函数或变量 (更简洁)
from helper_module import add, MODULE_VERSION
# 直接使用函数名和变量名,无需模块名前缀
result = add(10, 5)
print(f"10 + 5 的结果是: {result}")
print(f"再次确认版本: {MODULE_VERSION}")
如何运行:
在终端中,直接运行 main_script.py:
python main_script.py
输出结果:
你好, 小明! 欢迎来自 helper_module.py 的问候。
helper_module 的版本是: 1.0
10 + 5 的结果是: 15
再次确认版本: 1.0
使用 exec() 函数 - 动态执行代码块
exec() 是一个内置函数,它会动态地执行一个字符串形式的Python代码,你可以把整个文件的内容读出来,然后交给 exec() 去执行。

核心思想: 将文件内容作为字符串代码来执行。
如何操作:
# main_script.py
# 读取 helper_module.py 的全部内容
with open('helper_module.py', 'r', encoding='utf-8') as f:
code = f.read()
# 使用 exec() 执行这段代码
# 注意:exec() 会将代码在当前命名空间中执行
# 这意味着 helper_module.py 中定义的函数和变量会直接进入 main_script.py 的全局作用域
exec(code)
# 现在你可以直接使用 helper_module.py 中定义的函数和变量
greet("小红")
print(f"通过 exec() 执行后,add(20, 30) = {add(20, 30)}")
如何运行:
python main_script.py
输出结果:
你好, 小红! 欢迎来自 helper_module.py 的问候。
通过 exec() 执行后,add(20, 30) = 50
⚠️ 重要警告:
exec() 会执行任何给定的代码,如果文件内容来自不可信的来源(比如用户上传的文件),这会带来严重的安全风险(代码注入攻击)。永远不要对不可信的源使用 exec()。
使用 subprocess 模块 - 启动新的独立进程
这种方法会像在命令行中输入 python helper_module.py 一样,启动一个全新的、独立的Python进程来运行目标文件,两个脚本之间默认是隔离的,不能直接共享变量。
核心思想: 将另一个Python脚本当作一个独立的程序来运行。
如何操作:
helper_module.py 需要能独立运行,我们通常在它里面加一段 if __name__ == "__main__": 的代码。
修改 helper_module.py:
# helper_module.py
def greet(name):
print(f"你好, {name}! 欢迎来自 helper_module.py 的问候。")
def add(a, b):
return a + b
MODULE_VERSION = "1.0"
# --- 新增的代码 ---
# 这部分代码只有在文件被直接执行时才会运行
if __name__ == "__main__":
print("--- helper_module.py 开始独立运行 ---")
greet("世界")
print("--- helper_module.py 独立运行结束 ---")
main_script.py 的内容:
# main_script.py
import subprocess
# 使用 subprocess.run() 来执行另一个脚本
# 注意:这里需要传入一个列表,第一个元素是解释器,第二个是脚本文件名
print("--- main_script.py 准备调用 helper_module.py ---")
result = subprocess.run(['python', 'helper_module.py'])
print("\n--- helper_module.py 已经执行完毕 ---")
print(f"子进程的返回码是: {result.returncode}") # 0 表示成功
如何运行:
python main_script.py
输出结果:
--- main_script.py 准备调用 helper_module.py ---
--- helper_module.py 开始独立运行 ---
你好, 世界! 欢迎来自 helper_module.py 的问候。
--- helper_module.py 独立运行结束 ---
--- helper_module.py 已经执行完毕 ---
子进程的返回码是: 0
直接作为脚本运行 (使用 __import__ 或 importlib)
这种方法和方法一(import)非常相似,它提供了更底层的、动态的模块导入方式,通常在高级编程或元编程中使用,而不是日常编码。
如何操作:
# main_script.py
# 方法一:使用内置的 __import__ 函数 (不推荐直接使用,语法较复杂)
# module = __import__('helper_module')
# module.greet("通过 __import__")
# 方法二:使用标准库 importlib (更推荐和标准)
import importlib
# 动态导入模块
helper_module = importlib.import_module('helper_module')
# 使用导入的模块
helper_module.greet("通过 importlib")
如何运行:
python main_script.py
输出结果:
你好, 通过 importlib! 欢迎来自 helper_module.py 的问候。
总结与对比
| 方法 | 核心思想 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
import |
将文件作为模块导入 | 最规范、最安全,代码结构清晰,易于维护和复用 | 需要模块在 PYTHONPATH 中或与脚本同目录 |
99% 的情况,构建大型应用、库、项目时 |
exec() |
动态执行文件中的代码字符串 | 灵活性极高,可以动态执行任意代码 | 有安全风险,污染当前命名空间,调试困难 | 动态代码生成、运行时动态加载(确保代码来源可信) |
subprocess |
启动一个新的独立进程 | 隔离性好,可以调用不同Python版本的脚本,能获取脚本的标准输出 | 进程间通信复杂,性能开销大 | 需要将另一个脚本作为独立任务运行;需要其标准输出时 |
importlib |
动态地导入模块 | 比 __import__ 更清晰,是官方推荐的动态导入方式 |
代码稍显复杂,不如静态 import 直观 |
插件系统、按需加载模块、元编程等高级场景 |
最终建议
- 对于绝大多数情况,请使用
import语句。 这是Python设计的核心方式,也是最符合Pythonic(优雅)的写法。 - 只有在需要将一个脚本完全独立地作为任务来执行时,才考虑
subprocess。 - 请谨慎使用
exec(),并确保你完全理解其风险。 它主要用于处理你动态生成的、可信的代码。 importlib是一个强大的工具,但在日常开发中不如前三种常见,当你需要根据字符串或变量名来决定导入哪个模块时,它就派上用场了。
