杰瑞科技汇

python执行windows命令

在 Python 中执行 Windows 命令有多种方法,最常用的是 subprocess 模块,下面我将详细介绍几种常用的方法,并提供代码示例和最佳实践。

python执行windows命令-图1
(图片来源网络,侵删)

核心方法:subprocess 模块

subprocess 是 Python 官方推荐的用于创建和管理子进程的模块,功能强大且灵活,它替代了旧的 os.systemos.spawn* 等方法。


subprocess.run() (推荐,Python 3.5+)

这是最现代、最推荐的方法,它会执行命令,并等待其完成,然后返回一个 CompletedProcess 对象。

基本用法

import subprocess
# 执行一个简单的命令,例如列出当前目录的文件
# 注意:命令和参数需要作为一个列表传递
result = subprocess.run(['dir'], capture_output=True, text=True, shell=True)
# 检查命令是否执行成功
if result.returncode == 0:
    print("命令执行成功!")
    print("标准输出:")
    print(result.stdout)
else:
    print("命令执行失败!")
    print("标准错误:")
    print(result.stderr)

参数详解

  • ['dir']: 要执行的命令列表。dir 是一个 Windows 内部命令。
  • capture_output=True: 捕获标准输出和标准错误,你也可以使用 stdout=subprocess.PIPEstderr=subprocess.PIPE 来分别指定。
  • text=True: 将捕获的输出解码为文本字符串(默认为字节流),你也可以使用 universal_newlines=True,它们是等价的。
  • shell=True: 通过系统的命令行解释器(如 cmd.exe)来执行命令,这允许你使用 shell 特有的功能,比如管道 ()、通配符 () 等,但同时也带来了安全风险(如果命令字符串来自不可信的输入),对于简单的命令,shell=True 很方便。
  • check=True: 如果设置此参数,并且命令的返回码(exit code)不为 0,则会抛出 subprocess.CalledProcessError 异常。

使用 shell=True 的更简洁写法

当使用 shell=True 时,你可以直接传递一个字符串作为命令,而不是列表。

import subprocess
# 使用字符串,可以方便地使用 shell 特性
command = "dir /b"  # /b 参数表示只列出文件名,不包含额外信息
result = subprocess.run(command, capture_output=True, text=True, shell=True)
if result.returncode == 0:
    print("命令执行成功!")
    print(result.stdout)
else:
    print(f"命令执行失败,返回码: {result.returncode}")
    print(result.stderr)

subprocess.Popen() (最灵活)

Popen (process open) 是一个更底层的类,它不会等待命令执行完成,而是立即返回一个 Popen 对象,你需要手动管理进程的生命周期,这对于需要与进程进行实时交互(向进程发送输入或实时读取输出)的场景非常有用。

python执行windows命令-图2
(图片来源网络,侵删)

基本用法

import subprocess
# 创建一个子进程
# 注意:这里我们使用列表形式,并且不需要 shell=True 来执行简单的 dir 命令
# 但 dir 是一个内部命令,所以通常还是需要 shell=True
process = subprocess.Popen(['cmd', '/c', 'dir'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
# 等待进程结束并获取输出
stdout, stderr = process.communicate()
print(f"返回码: {process.returncode}")
if process.returncode == 0:
    print("标准输出:")
    print(stdout)
else:
    print("标准错误:")
    print(stderr)

Popen 的优势:实时交互

import subprocess
# 启动一个交互式命令,ping
# shell=True 让我们可以直接使用 'ping' 命令
process = subprocess.Popen('ping www.google.com', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
# 实时打印输出
for line in process.stdout:
    print(line, end='') # end='' 因为 line 中已经包含了换行符
# 等待进程结束
process.wait()
print(f"\nPing 命令结束,返回码: {process.returncode}")

os.system() (不推荐,仅作了解)

这是最古老、最简单的方法,但功能有限,不推荐在新代码中使用,它执行命令,并打印输出到终端,但很难捕获输出。

import os
# os.system 会直接在控制台打印 dir 的结果
# 返回的是命令执行后的退出码
return_code = os.system('dir')
print(f"\n命令执行完毕,返回码: {return_code}")

为什么不推荐?

  • 无法捕获输出:无法将命令的输出作为字符串获取,只能在控制台看到。
  • 安全性差:容易受到 shell 注入攻击。
  • 功能弱:无法进行复杂的进程控制。

os.popen() (不推荐,仅作了解)

os.popen 可以打开一个管道,允许你读取命令的输出或向命令写入输入,它比 os.system 稍好,但仍然不如 subprocess 灵活和安全。

import os
# 打开一个管道来读取 'dir' 命令的输出
# 返回一个文件对象,可以像读取文件一样读取
with os.popen('dir /b') as pipe:
    output = pipe.read()
print("通过 os.popen 获取的输出:")
print(output)

总结与最佳实践

方法 优点 缺点 推荐场景
subprocess.run() 现代、推荐、安全、功能全面 相对较新 (Python 3.5+) 绝大多数情况下的首选
subprocess.Popen() 最灵活,支持实时交互和复杂进程管理 代码更复杂,需要手动管理进程 需要与子进程进行持续交互时(如 SSH 客户端、游戏服务器)。
os.system() 极其简单 无法捕获输出,不安全,功能弱 快速执行一个命令且不关心输出时(不推荐)。
os.popen() 可以捕获输出 已被 subprocess 淘汰,功能有限 维护非常旧的 Python 代码时。

最佳实践建议

  1. 首选 subprocess.run():对于绝大多数执行 Windows 命令的需求,subprocess.run() 是最佳选择。
  2. 何时使用 shell=True
    • 当你的命令是单个字符串,并且需要使用*管道 ()、重定向 (>, <) 或通配符 (``)** 等 shell 特性时。
    • 安全警告:如果命令的任何部分来自用户输入,绝对不要使用 shell=True,因为这可能导致命令注入攻击,如果必须使用,请务必对输入进行严格的清理和验证。
  3. 何时使用 shell=False (默认)
    • 当你将命令和参数作为列表传递时,这是更安全的方式,Python 会直接执行程序,而不经过 shell 解释。
    • 执行一个外部程序如 python.exesubprocess.run(['python', 'my_script.py'])

一个综合示例

import subprocess
import time
def run_command(command, use_shell=False):
    """
    执行一个命令并打印其结果。
    :param command: 命令字符串或列表。
    :param use_shell: 是否使用 shell 解释器。
    """
    print(f"--- 执行命令: {' '.join(command) if isinstance(command, list) else command} ---")
    try:
        # 使用 check=True 会在命令失败时抛出异常
        result = subprocess.run(
            command,
            capture_output=True,
            text=True,
            shell=use_shell,
            check=True,
            encoding='gbk', # 在中文Windows系统上,很多命令的输出是GBK编码,指定可以避免乱码
            errors='ignore' # 如果解码失败,忽略错误字符
        )
        print("标准输出:")
        print(result.stdout)
    except subprocess.CalledProcessError as e:
        print(f"命令执行失败,返回码: {e.returncode}")
        print("标准错误:")
        print(e.stderr)
    except FileNotFoundError:
        print(f"错误: 找不到命令或程序,请检查路径是否正确。")
    except Exception as e:
        print(f"发生未知错误: {e}")
    finally:
        print("--- 命令执行结束 ---\n")
# 示例1: 使用列表执行,更安全
run_command(['ping', '-n', '4', '127.0.0.1'], use_shell=False)
# 示例2: 使用字符串和 shell=True,方便使用管道
run_command('dir /b | findstr "py"', use_shell=True)
# 示例3: 执行一个不存在的命令
run_command(['non_existent_command'], use_shell=False)
python执行windows命令-图3
(图片来源网络,侵删)
分享:
扫描分享到社交APP
上一篇
下一篇