导入模块(最常用、最推荐)
这是 Python 的核心机制,当你把一个脚本当作一个“模块”来导入时,你可以直接使用它定义的函数、类和变量。

适用场景:
- 你想复用另一个脚本中的代码(函数、类)。
- 你想在主程序中执行另一个脚本的一部分逻辑。
- 两个脚本需要共享数据。
步骤:
-
创建一个可被导入的脚本(
my_module.py) 这个脚本应该包含一些可重用的代码。# my_module.py def greet(name): """一个简单的问候函数""" print(f"Hello, {name}! Welcome to the module.") def add(a, b): """一个加法函数""" return a + b # 如果这个脚本被直接运行(而不是被导入),下面的代码会执行 if __name__ == "__main__": print("This block runs only when my_module.py is executed directly.") greet("Direct Runner") print(f"5 + 3 = {add(5, 3)}")关键点:
if __name__ == "__main__":是一个非常重要的 Python 约定。
(图片来源网络,侵删)- 当你直接运行
python my_module.py时,__name__的值是"__main__",if里面的代码会执行。 - 当你从另一个脚本
import my_module时,__name__的值是模块名"my_module",if里面的代码不会执行,这使得你的模块既可以作为脚本独立运行,也可以作为模块被导入复用。
- 当你直接运行
-
在主脚本中调用它(
main_script.py)# main_script.py # 导入整个模块 import my_module # 调用模块中的函数 my_module.greet("Alice") # 调用另一个函数 sum_result = my_module.add(10, 25) print(f"The sum is: {sum_result}") # 只导入特定的函数,这样可以直接使用函数名,无需模块名前缀 from my_module import greet, add greet("Bob") print(f"Another sum: {add(100, 200)}") # 导入整个模块并给它一个别名 import my_module as mm mm.greet("Charlie")
运行 main_script.py 的输出:
Hello, Alice! Welcome to the module.
The sum is: 35
Hello, Bob! Welcome to the module.
Another sum: 300
Hello, Charlie! Welcome to the module.
注意,my_module.py 中 if __name__ == "__main__": 的代码没有被执行,因为它是被导入的。
使用 subprocess 模块(作为独立进程运行)
如果你想完全独立地运行另一个 Python 脚本,就像在命令行中输入命令一样,并且需要捕获它的输出或传递参数,subprocess 是最佳选择。

适用场景:
- 你想将另一个脚本作为一个完全独立的“黑盒”任务来执行。
- 你需要向被调用的脚本传递命令行参数。
- 你需要获取被调用脚本的输出结果(标准输出、标准错误)。
- 被调用的脚本可能会执行很长时间,你不希望阻塞主程序。
示例:
-
创建一个可被命令行调用的脚本(
script_to_run.py) 这个脚本可以接受命令行参数。# script_to_run.py import sys import time print(f"Script started. Arguments received: {sys.argv}") if len(sys.argv) > 1: name = sys.argv[1] print(f"Processing for {name}...") time.sleep(2) # 模拟一个耗时操作 print(f"Done processing for {name}.") else: print("No arguments provided.") print("Script finished.") -
在主脚本中使用
subprocess调用它# main_script.py import subprocess import sys # --- 场景1: 运行一个不带参数的脚本 --- print("--- Running script without arguments ---") try: # subprocess.run() 会执行命令并等待它完成 result = subprocess.run( [sys.executable, "script_to_run.py"], # 使用 sys.executable 来确保使用当前 Python 解释器 capture_output=True, # 捕获标准输出和标准错误 text=True, # 将输出解码为文本 check=True # 如果脚本返回非零退出码(表示错误),则抛出异常 ) print("Script executed successfully!") print("STDOUT:", result.stdout) print("STDERR:", result.stderr) except subprocess.CalledProcessError as e: print(f"Script failed with error code {e.returncode}") print("STDOUT:", e.stdout) print("STDERR:", e.stderr) print("\n" + "="*40 + "\n") # --- 场景2: 运行一个带参数的脚本 --- print("--- Running script with arguments ---") try: # 使用列表形式传递命令和参数 result = subprocess.run( [sys.executable, "script_to_run.py", "DataProcessor"], capture_output=True, text=True, check=True ) print("Script with args executed successfully!") print("STDOUT:", result.stdout) except subprocess.CalledProcessError as e: print(f"Script with args failed.") print("STDOUT:", e.stdout) print("STDERR:", e.stderr) print("\n" + "="*40 + "\n") # --- 场景3: 实时打印输出 --- print("--- Running script and printing output in real-time ---") # 使用 Popen 可以更好地控制子进程 process = subprocess.Popen( [sys.executable, "script_to_run.py", "RealTimeUser"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) # 实时读取并打印输出 for line in iter(process.stdout.readline, ''): print(line, end='') # 等待进程结束并检查返回码 process.wait() if process.returncode != 0: print(f"\nProcess failed with return code {process.returncode}") # 读取并打印错误输出 for line in iter(process.stderr.readline, ''): print(line, end='') else: print("\nProcess completed successfully.")
运行 main_script.py 的输出:
--- Running script without arguments ---
Script executed successfully!
STDOUT:
Script started. Arguments received: ['script_to_run.py']
No arguments provided.
Script finished.
STDERR:
========================================
--- Running script with arguments ---
Script with args executed successfully!
STDOUT:
Script started. Arguments received: ['script_to_run.py', 'DataProcessor']
Processing for DataProcessor...
Done processing for DataProcessor.
Script finished.
========================================
--- Running script and printing output in real-time ---
Script started. Arguments received: ['script_to_run.py', 'RealTimeUser']
Processing for RealTimeUser...
Done processing for RealTimeUser.
Script finished.
Process completed successfully.
动态导入(高级用法)
有时你只有在运行时才知道要导入哪个模块,这时可以使用 importlib。
适用场景:
- 插件系统。
- 根据配置文件动态加载不同的功能模块。
示例:
# main_script.py
import importlib
module_name = "my_module" # 这个名字可以来自配置文件或用户输入
try:
# 动态导入模块
my_module = importlib.import_module(module_name)
# 现在可以像正常导入一样使用它
my_module.greet("Dynamic User")
# 你甚至可以动态调用函数
func_name = "add"
if hasattr(my_module, func_name):
func_to_call = getattr(my_module, func_name)
result = func_to_call(7, 8)
print(f"Dynamically called {func_name}(7, 8) = {result}")
except ImportError:
print(f"Error: Module '{module_name}' not found.")
总结与选择
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
import 模块 |
最常用、最 Pythonic,共享内存,代码复用性强,性能高。 | 被导入的代码会在导入时执行,共享全局命名空间,可能导致副作用。 | 绝大多数情况,当你想复用代码,逻辑紧密耦合时。 |
subprocess |
完全隔离,可以将脚本视为独立的命令行工具,易于传递参数和捕获I/O。 | 开销大,创建新进程,通信慢(通过文件描述符/管道),不适合高频调用。 | 当需要独立执行、并行任务、或处理外部命令式脚本时。 |
importlib |
高度灵活,实现插件化架构。 | 代码可读性稍差,增加了运行时复杂性。 | 需要根据运行时条件动态加载模块的插件系统或高级框架。 |
给你的建议:
- 首选
import:如果你的两个脚本需要共享数据和逻辑,或者你想复用其中的函数和类,直接import它,这是 Python 的标准做法。 - 次选
subprocess:如果你只是想“运行”另一个脚本,不关心它的内部实现,或者需要把它当作一个独立的任务来处理(比如定时任务、并行处理),并且需要传递命令行参数,那么使用subprocess。 - 谨慎使用
importlib:除非你明确需要一个动态的插件系统,否则一般不需要用到它。
