Python中执行Shell命令无法获取标准输出的问题
在Python中调用Shell命令并捕获输出的正确方式
我来帮你搞定这个问题!你之前用os.system()和subprocess.Popen()没成功,主要是对这几个API的用法没摸透,咱们一步步来解决:
为什么os.system()不行?
os.system()这个函数只返回命令的退出状态码(0代表执行成功,非0代表出错),根本不会捕获命令的标准输出。所以你把它赋值给变量x,得到的不是lsusb | sed的输出,而是一个数字,这肯定不是你想要的结果。
正确的实现方法
方法1:用subprocess.check_output()(最简洁)
这是Python官方推荐的、捕获命令输出的简洁方式,适合命令执行成功的场景,如果命令出错会直接抛出异常,方便你处理错误:
import subprocess try: # shell=True 让Shell帮我们解析管道符|,text=True直接返回字符串(不用手动decode) output = subprocess.check_output( "lsusb | sed -e 's/.*ID \\([a-f0-9]\\+:[a-f0-9]\\+\\).*/\\1/g'", shell=True, text=True ) # 去掉输出首尾的换行和空格,让结果更干净 print(output.strip()) except subprocess.CalledProcessError as e: print(f"命令执行出错啦:{e}")
注意哦:Python字符串里的反斜杠需要转义,所以原来Shell命令里的\(要写成\\(,或者你也可以用原始字符串r""来避免转义,比如把命令写成r"lsusb | sed -e 's/.*ID \([a-f0-9]\+:[a-f0-9]\+\).*/\1/g'"。
方法2:用subprocess.Popen()(更灵活)
如果需要更精细地控制进程(比如处理输入、异步执行),可以用Popen配合communicate()来捕获输出:
import subprocess # 同样需要shell=True来解析管道,stdout=PIPE表示捕获标准输出 process = subprocess.Popen( "lsusb | sed -e 's/.*ID \\([a-f0-9]\\+:[a-f0-9]\\+\\).*/\\1/g'", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) # 获取输出和错误信息,同时等待进程结束 stdout, stderr = process.communicate() if process.returncode == 0: print(stdout.strip()) else: print(f"命令执行出错,错误信息:{stderr.strip()}")
方法3:不用shell=True(更安全)
如果你的命令涉及用户输入,用shell=True会有Shell注入的安全风险,这时候可以把命令拆分成列表,手动处理管道:
import subprocess # 先执行lsusb,把它的输出作为sed的输入 lsusb_proc = subprocess.Popen(["lsusb"], stdout=subprocess.PIPE, text=True) sed_proc = subprocess.Popen( ["sed", "-e", "s/.*ID \\([a-f0-9]\\+:[a-f0-9]\\+\\).*/\\1/g"], stdin=lsusb_proc.stdout, stdout=subprocess.PIPE, text=True ) # 关闭lsusb的stdout,让它在sed退出时收到SIGPIPE lsusb_proc.stdout.close() stdout, stderr = sed_proc.communicate() if sed_proc.returncode == 0: print(stdout.strip()) else: print(f"命令执行出错:{stderr.strip()}")
内容的提问来源于stack exchange,提问作者Batcastle
相关产品推荐
相关产品推荐

