杰瑞科技汇

python中调用python脚本

在 Python 中调用另一个 Python 脚本(模块)有多种方法,适用于不同的场景,例如简单的代码复用、参数传递、进程管理等,下面我将从最基础到最复杂的场景,为你详细介绍几种常用方法。

python中调用python脚本-图1
(图片来源网络,侵删)

直接导入模块 (Import)

这是最基本、最常用的方法,适用于将一个脚本的功能作为模块导入到另一个脚本中使用。

适用场景:

  • 你想复用另一个脚本中的函数、类或变量。
  • 被调用的脚本是一个库或工具集的一部分。

如何做:

  1. 确保 my_module.pymain_script.py 在同一个目录下,或者 my_module.py 所在的目录在 Python 的搜索路径中。
  2. main_script.py 中使用 import my_module 来导入。

示例:

python中调用python脚本-图2
(图片来源网络,侵删)

my_module.py (被调用的脚本)

# 这是一个可以被其他脚本导入的模块
def greet(name):
    """一个简单的问候函数"""
    print(f"Hello, {name} from my_module!")
def add(a, b):
    """一个加法函数"""
    return a + b
# 如果这个脚本被直接运行,而不是被导入,这里的代码会执行
if __name__ == "__main__":
    print("This is my_module.py being run directly.")
    greet("Direct Caller")

main_script.py (调用者脚本)

# 导入 my_module 模块
import my_module
# 调用模块中的函数
my_module.greet("Alice")
# 使用模块中的函数
result = my_module.add(5, 3)
print(f"The result of add(5, 3) is: {result}")
# 直接访问模块中的变量(如果有的话)
# print(my_module.some_variable)

运行 main_script.py 的输出:

Hello, Alice from my_module!
The result of add(5, 3) is: 8

注意: if __name__ == "__main__": 是一个非常重要的 Python 约定,当脚本被直接运行时,__name__ 的值是 "__main__";当脚本被其他脚本导入时,__name__ 的值是模块名(这里是 "my_module"),上面的 print 语句只在直接运行 my_module.py 时才会执行。

python中调用python脚本-图3
(图片来源网络,侵删)

使用 exec() 函数

exec() 函数可以执行存储在字符串或文件中的 Python 代码,这种方法非常灵活,但也要注意其安全风险。

适用场景:

  • 动态执行代码,例如代码是从文件或用户输入中读取的。
  • 需要在运行时决定执行哪个脚本。

如何做: 使用 exec(open('filename').read()) 来读取并执行整个文件。

示例:

main_script.py (调用者脚本)

script_path = 'my_module.py'
try:
    with open(script_path, 'r') as file:
        script_code = file.read()
    # 执行读取到的代码
    exec(script_code)
    print("\nExecuted my_module.py successfully.")
except FileNotFoundError:
    print(f"Error: The file {script_path} was not found.")
except Exception as e:
    print(f"An error occurred: {e}")

运行 main_script.py 的输出:

This is my_module.py being run directly.
Hello, Direct Caller from my_module!
Executed my_module.py successfully.

⚠️ 重要警告: exec() 会执行任何它接收到的代码,包括恶意代码。绝对不要使用 exec() 来执行不受信任的代码(例如来自网络用户的输入),这会带来严重的安全风险。


使用 subprocess 模块 (推荐用于独立进程)

当你希望将另一个 Python 脚本作为一个独立的进程来运行时,subprocess 模块是最佳选择,这可以隔离环境,避免命名冲突,并且可以捕获脚本的输出。

适用场景:

  • 你想完全分离两个脚本的运行环境。
  • 需要向被调用的脚本传递命令行参数。
  • 需要获取被调用脚本的输出结果(标准输出、标准错误)。
  • 被调用的脚本是一个独立的命令行工具。

如何做: 使用 subprocess.run() 是最现代、推荐的方式。

示例:

cli_tool.py (一个简单的命令行工具)

import sys
import argparse
def main():
    parser = argparse.ArgumentParser(description="A simple CLI tool.")
    parser.add_argument('--name', type=str, default='World', help="The name to greet.")
    parser.add_argument('--count', type=int, default=1, help="The number of times to greet.")
    args = parser.parse_args()
    for _ in range(args.count):
        print(f"Hello, {args.name}!")
if __name__ == "__main__":
    main()

main_script.py (调用者脚本)

import subprocess
# 场景1: 运行脚本,不关心输出
print("--- Running script without capturing output ---")
subprocess.run(['python', 'cli_tool.py', '--name', 'Bob'])
# 场景2: 运行脚本,并捕获输出
print("\n--- Running script and capturing output ---")
result = subprocess.run(
    ['python', 'cli_tool.py', '--name', 'Charlie', '--count', '3'],
    capture_output=True,  # 捕获标准输出和标准错误
    text=True            # 将输出解码为文本
)
print(f"Return code: {result.returncode}")
print(f"Stdout:\n{result.stdout}")
print(f"Stderr:\n{result.stderr}")
# 检查是否执行成功
if result.returncode == 0:
    print("\nThe script executed successfully!")
else:
    print("\nThe script failed.")

运行 main_script.py 的输出:

--- Running script without capturing output ---
Hello, Bob!
--- Running script and capturing output ---
Return code: 0
Stdout:
Hello, Charlie!
Hello, Charlie!
Hello, Charlie!
Stderr:
The script executed successfully!

使用 os.system() 函数 (较旧的方式)

这是 subprocess 模块出现之前的方式,功能相对简单,它会在一个子 shell 中执行命令。

适用场景:

  • 简单的命令执行,不需要复杂的参数传递或输出捕获。
  • 维护旧的代码库。

如何做: 将命令作为一个字符串传递给 os.system()

示例:

main_script.py (调用者脚本)

import os
print("--- Running script with os.system ---)
# 使用字符串形式执行命令
# 注意引号的使用,以防 shell 解析错误
os.system('python cli_tool.py --name "David"')

运行 main_script.py 的输出:

--- Running script with os.system ---
Hello, David!

注意: os.system() 不如 subprocess 灵活和安全,通常建议在新代码中使用 subprocess


总结与选择建议

方法 优点 缺点 推荐场景
import 代码集成度高,共享内存,效率高,易于调试 共享全局命名空间,可能产生副作用 代码复用和模块化开发(首选)
exec() 极其灵活,可动态执行任意代码 安全风险极高,难以调试,性能较差 执行可信的、动态生成的代码(非常谨慎使用)
subprocess 隔离环境,可传递参数,可捕获输入/输出,功能强大 进程间通信开销比 import 需要独立进程、命令行交互或隔离环境(强烈推荐)
os.system() 简单易用 功能有限,不灵活,不安全,已过时 简单的、一次性的命令执行(不推荐新项目使用)

  • 如果你想在一个脚本中使用另一个脚本的函数和变量,请用 import
  • 如果你想把另一个脚本当作一个独立的程序来运行,并给它传参数、收结果,请用 subprocess
分享:
扫描分享到社交APP
上一篇
下一篇