标签导航:

python subprocess模块与shell交互:如何避免代码卡死并正确获取输出?

Python subprocess 模块与Shell交互的进阶技巧

在Python系统管理或自动化任务中,经常需要与Shell交互。本文探讨如何使用subprocess模块高效地与Shell进行多次交互,如同在终端中一样灵活地执行命令并获取结果。

许多开发者尝试使用subprocess.Popen模拟Shell交互,却常遇到代码卡死或无法获取预期输出的问题。例如,直接用subprocess.Popen启动Shell进程(如/bin/bash),然后循环输入命令,往往得不到正确响应。

根本原因在于,Shell命令通常以换行符( )作为结束标志。仅发送命令字符串,Shell无法识别命令结束,导致命令执行失败,程序陷入阻塞。

让我们分析一段典型的错误代码:

import subprocess

process = subprocess.Popen('/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

while True:
    cmd = input("$ ")
    if cmd == "exit":
        break
    cmd = cmd.encode('utf-8')

    print('cmd',cmd)
    process.stdin.write(cmd)
    process.stdin.flush()
    output = process.stdout.readline().decode('utf-8')
    print(output.strip())

这段代码的缺陷在于缺少在发送命令后添加换行符。这导致Shell无法正确解析命令,程序卡住。

解决方法是在发送命令前,将命令字符串编码后添加换行符b' ':

import subprocess

process = subprocess.Popen('/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

while True:
    cmd = input("$ ")
    if cmd == "exit":
        break
    cmd = cmd.encode('utf-8') + b'
'

    print('cmd',cmd)
    process.stdin.write(cmd)
    process.stdin.flush()
    output = process.stdout.readline().decode('utf-8')
    print(output.strip())

通过添加b' ',Shell能够正确识别每个命令的结束,实现与Shell的交互式操作,达到预期效果。 Python脚本可以像在终端一样,与Shell进行多次交互,输入命令并获取输出结果。