杰瑞科技汇

Python external模块如何安装使用?

Python 标准库中 没有一个名为 external 的官方模块

Python external模块如何安装使用?-图1
(图片来源网络,侵删)

当你听到或看到 "external" 这个词时,它通常不是指一个具体的模块,而是指代一个概念一系列实践,即“在 Python 程序中调用外部资源或程序”

你的问题“python external模块”可以理解为以下几个核心方向:

  1. 执行外部命令/脚本:如何让你的 Python 脚本像在终端里一样运行其他命令行程序(如 ls, git, docker 等)。
  2. 与外部程序进行交互:如何启动一个外部程序,并与其进行实时的数据交换(发送输入、读取输出)。
  3. 调用外部可执行文件:如何运行编译好的二进制文件(如 .exe, .sh 脚本等)。
  4. 使用第三方库来简化外部调用:社区中有哪些优秀的库可以更优雅、更安全地完成上述任务。

下面我将围绕这四个方向,为你详细解释 Python 是如何与“外部”世界交互的。


执行外部命令(最常见的需求)

这是最常见的需求,比如你想在 Python 脚本中执行 git statusls -l,Python 提供了多种方式,从简单到强大。

Python external模块如何安装使用?-图2
(图片来源网络,侵删)

os.system() - 最简单,但功能有限

这是最直接的方式,它会在一个子 shell 中执行你的命令,并返回命令的退出状态码。

import os
# 执行一个简单的命令,打印结果到终端
# 返回值是命令执行后的退出码 (0 表示成功)
return_code = os.system('echo "Hello from Python"')
print(f"命令执行退出码: {return_code}")
# 执行一个带参数的命令
os.system('ls -l')

缺点

  • 无法获取命令的输出os.system() 只能将命令的输出打印到标准输出(你的终端),无法在 Python 程序中捕获和处理这个输出。
  • 不安全:如果命令参数来自用户输入,很容易造成命令注入漏洞。
  • 功能单一:无法处理复杂的交互。

subprocess 模块 - 现代、强大、推荐

subprocess 是 Python 官方推荐用于管理子进程的模块,功能非常强大,可以替代旧的 os.system, os.spawn 等。

subprocess.run() - 推荐的通用方法

这是 Python 3.5+ 引入的现代化接口,非常灵活和安全。

Python external模块如何安装使用?-图3
(图片来源网络,侵删)
import subprocess
# --- 示例1: 执行命令并获取输出 ---
# capture_output=True 会捕获标准输出和标准错误
# text=True 会将输出解码为字符串(默认是字节)
# check=True 如果命令返回非零退出码,会抛出 CalledProcessError 异常
try:
    result = subprocess.run(['ls', '-l'], capture_output=True, text=True, check=True)
    # result.stdout 是命令的标准输出
    print("命令输出:")
    print(result.stdout)
    # result.stderr 是命令的标准错误
    # result.returncode 是退出码
    print(f"退出码: {result.returncode}")
except subprocess.CalledProcessError as e:
    print(f"命令执行失败: {e}")
    print(f"错误输出: {e.stderr}")
# --- 示例2: 安全地处理用户输入(防止命令注入)---
# 使用列表形式传递命令和参数,而不是字符串
user_input = "my_file.txt"
command = ['cat', user_input]  # 这样是安全的
# command = f'cat {user_input}' # 这样是危险的!user_input 是 "my_file.txt; rm -rf /",后果不堪设想
try:
    result = subprocess.run(command, capture_output=True, text=True, check=True)
    print("\n文件内容:")
    print(result.stdout)
except FileNotFoundError:
    print(f"错误: 文件 {user_input} 不存在")
except subprocess.CalledProcessError as e:
    print(f"命令执行失败: {e.stderr}")

subprocess.Popen() - 更底层的控制

当你需要与子进程进行实时交互时(比如启动一个交互式 shell 或一个持续运行的程序),Popen 是更好的选择,它不会像 run() 那样等待命令执行完毕。

import subprocess
# 启动一个子进程
proc = subprocess.Popen(['ping', '-c', '5', 'google.com'], 
                        stdout=subprocess.PIPE, 
                        stderr=subprocess.PIPE, 
                        text=True)
# 实时读取输出
while True:
    output = proc.stdout.readline()
    if output == '' and proc.poll() is not None:
        break
    if output:
        print(output.strip())
# 等待进程结束,并获取返回码
return_code = proc.wait()
print(f"\nPing 命令执行完毕,退出码: {return_code}")

与外部程序进行交互

使用 subprocess.Popen 可以实现交互,我们以 bc (一个命令行计算器) 为例。

import subprocess
# 启动 bc 进程
proc = subprocess.Popen(['bc'], 
                        stdin=subprocess.PIPE, 
                        stdout=subprocess.PIPE, 
                        stderr=subprocess.PIPE, 
                        text=True)
# 发送输入 "2 + 2",然后发送 "quit" 来退出
proc.stdin.write("2 + 2\n")
proc.stdin.write("quit\n")
proc.stdin.close() # 关闭输入流,告诉 bc 没有更多输入了
# 读取所有输出
stdout, stderr = proc.communicate()
print("bc 计算结果:")
print(stdout) # 应该会输出 "4\n"

调用外部可执行文件

这和执行命令本质上是一样的,无论是 .exe 文件、.sh 脚本还是其他任何可执行文件,Python 都可以通过 subprocess 模块来调用。

在 Windows 上调用 .exe 文件:

import subprocess
# 假设你有一个 my_app.exe 文件
subprocess.run(['my_app.exe', '--input', 'data.txt'])

在 Linux/macOS 上调用 .sh 脚本:

import subprocess
# 脚本需要有执行权限 (chmod +x my_script.sh)
subprocess.run(['./my_script.sh', 'arg1', 'arg2'])

使用第三方库简化外部调用

除了标准库,社区也开发了许多优秀的第三方库来处理外部调用,它们通常提供了更简洁的 API 或特定领域的功能。

sh 库 - 一个非常流行的替代品

sh 库的设计哲学是让调用外部命令就像调用普通 Python 函数一样自然。

安装:

pip install sh

使用示例:

from sh import git, ls
# 像调用函数一样调用 git
print(gl="en") # git status --porcelain
# 获取输出
try:
    output = ls("-l")
    print(output)
except sh.ErrorReturnCode as e:
    print(f"命令执行失败: {e.stderr}")

plumbum 库 - 功能强大的工具链

plumbum 是一个功能更全面的库,不仅包含命令调用,还提供了路径操作、进程管理等工具。

安装:

pip install plumbum

使用示例:

from plumbum import local, FG
# FG 表示将子进程的输入输出连接到当前终端(前台运行)
# local.path("ls") -l | FG
# 也可以捕获输出
from plumbum import Command
ls = Command("ls")
try:
    output = ls("-l")
    print(output)
except local.ProcessExecutionError as e:
    print(f"命令执行失败: {e.stderr}")

总结与最佳实践

方法 优点 缺点 适用场景
os.system() 简单直接,无需导入 无法获取输出,不安全,功能弱 快速执行简单命令,不关心结果
subprocess.run() 现代、安全、灵活,推荐首选 相对 os.system 稍显复杂 绝大多数情况下的首选,需要获取输出、处理错误等
subprocess.Popen() 功能最强大,支持实时交互 API 最复杂,需要手动管理进程生命周期 需要与子进程持续交互(如 shell、游戏服务器)
sh / plumbum 语法简洁,易于使用 需要额外安装,可能引入依赖 需要在大量地方调用外部命令,追求代码简洁性的项目

核心建议

  1. 忘记 os.system():除非你只是想在脚本里快速打印个日志,否则不要用它。
  2. subprocess.run() 开始:对于 99% 的外部命令调用需求,subprocess.run() 都能完美胜任,它提供了安全、可控和现代化的接口。
  3. 在需要交互时用 Popen():当你发现 run() 无法满足需求(比如需要一边输入一边等待输出)时,再考虑使用 Popen()
  4. 考虑第三方库:如果你的项目核心逻辑就是调用大量外部命令,并且希望代码更优雅,shplumbum 是非常好的选择。
分享:
扫描分享到社交APP
上一篇
下一篇