运行shell命令并捕获输出
我想编写一个函数,该函数将执行shell命令并以字符串形式返回其输出,无论它是错误消息还是成功消息。 我只想获得与命令行相同的结果。
能做到这一点的代码示例是什么?
例如:
def run_command(cmd):# ??????print run_command('mysqladmin create test -uroot -pmysqladmin12')
# Should output something like:
# mysqladmin: CREATE DATABASE failed; error: 'Can't create database 'test'; database exists'
#1楼
Vartec的答案无法读取所有行,因此我制作了一个可以读取的版本:
def run_command(command):p = subprocess.Popen(command,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)return iter(p.stdout.readline, b'')
用法与接受的答案相同:
command = 'mysqladmin create test -uroot -pmysqladmin12'.split()
for line in run_command(command):print(line)
#2楼
您的里程可能会有所不同,我尝试使用@senderle在Windows 2.6.5上的Windows中使用Vartec的解决方案,但是我遇到了错误,并且没有其他解决方案起作用。 我的错误是: WindowsError: [Error 6] The handle is invalid
。
我发现我必须为每个句柄分配PIPE才能使其返回我期望的输出-以下内容对我有用。
import subprocessdef run_command(cmd):"""given shell command, returns communication tuple of stdout and stderr"""return subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE).communicate()
并像这样调用( [0]
获取元组的第一个元素stdout
):
run_command('tracert 11.1.0.1')[0]
学习更多之后,我相信我需要这些管道参数,因为我正在使用不同句柄的自定义系统上工作,因此必须直接控制所有std。
要停止控制台弹出窗口(在Windows中),请执行以下操作:
def run_command(cmd):"""given shell command, returns communication tuple of stdout and stderr"""# instantiate a startupinfo obj:startupinfo = subprocess.STARTUPINFO()# set the use show window flag, might make conditional on being in Windows:startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW# pass as the startupinfo keyword argument:return subprocess.Popen(cmd,stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, startupinfo=startupinfo).communicate()run_command('tracert 11.1.0.1')
#3楼
如果您需要在多个文件上运行一个shell命令,那么这对我就成功了。
import os
import subprocess# Define a function for running commands and capturing stdout line by line
# (Modified from Vartec's solution because it wasn't printing all lines)
def runProcess(exe): p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)return iter(p.stdout.readline, b'')# Get all filenames in working directory
for filename in os.listdir('./'):# This command will be run on each filecmd = 'nm ' + filename# Run the command and capture the output line by line.for line in runProcess(cmd.split()):# Eliminate leading and trailing whitespaceline.strip()# Split the output output = line.split()# Filter the output and print relevant linesif len(output) > 2:if ((output[2] == 'set_program_name')):print filenameprint line
编辑:刚刚看到了JF Sebastian的建议的Max Persson的解决方案。 继续前进,并纳入。
#4楼
这是一个棘手但超级简单的解决方案,可在许多情况下使用:
import os
os.system('sample_cmd > tmp')
print open('tmp', 'r').read()
使用命令的输出创建一个临时文件(这里是tmp),您可以从中读取所需的输出。
注释中的额外说明:如果是一次性作业,则可以删除tmp文件。 如果您需要多次执行此操作,则无需删除tmp。
os.remove('tmp')
#5楼
对于以下问题,我对同一问题的口味略有不同:
- 当STDOUT消息在STDOUT缓冲区中累积时(即实时)捕获并返回它们。
- @vartec通过使用生成器和'yield'在Python上解决了这个问题
上方关键字
- @vartec通过使用生成器和'yield'在Python上解决了这个问题
- 打印所有STDOUT行( 即使在可以完全读取STDOUT缓冲区之前退出进程 )
- 不要浪费CPU周期以高频率轮询进程
- 检查子流程的返回码
- 如果获得非零错误返回码,则打印STDERR(与STDOUT分开)。
我结合并调整了先前的答案,以得出以下结论:
import subprocess
from time import sleepdef run_command(command):p = subprocess.Popen(command,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)# Read stdout from subprocess until the buffer is empty !for line in iter(p.stdout.readline, b''):if line: # Don't print blank linesyield line# This ensures the process has completed, AND sets the 'returncode' attrwhile p.poll() is None: sleep(.1) #Don't waste CPU-cycles# Empty STDERR buffererr = p.stderr.read()if p.returncode != 0:# The run_command() function is responsible for logging STDERR print("Error: " + str(err))
此代码将与以前的答案相同地执行:
for line in run_command(cmd):print(line)
#6楼
我遇到了同样的问题,但是想出了一种非常简单的方法:
import subprocess
output = subprocess.getoutput("ls -l")
print(output)
希望能帮上忙
注意:此解决方案特定于Python3,因为subprocess.getoutput subprocess.getoutput()
在Python2中不起作用
#7楼
您可以使用以下命令来运行任何shell命令。 我在ubuntu上使用过它们。
import os
os.popen('your command here').read()
注意:自python 2.6起不推荐使用。 现在,您必须使用subprocess.Popen
。 以下是示例
import subprocessp = subprocess.Popen("Your command", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
print p.split("\n")
#8楼
例如,execute('ls -ahl')区分了三种/四种可能的收益和OS平台:
- 无输出,但运行成功
- 输出空行,运行成功
- 运行失败
- 输出一些东西,成功运行
功能如下
def execute(cmd, output=True, DEBUG_MODE=False):
"""Executes a bash command.
(cmd, output=True)
output: whether print shell output to screen, only affects screen display, does not affect returned values
return: ...regardless of output=True/False...returns shell output as a list with each elment is a line of string (whitespace stripped both sides) from outputcould be [], ie, len()=0 --> no output; [''] --> output empty line; None --> error occured, see belowif error ocurs, returns None (ie, is None), print out the error message to screen
"""
if not DEBUG_MODE:print "Command: " + cmd# https://stackoverflow.com/a/40139101/2292993def _execute_cmd(cmd):if os.name == 'nt' or platform.system() == 'Windows':# set stdin, out, err all to PIPE to get results (other than None) after run the Popen() instancep = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)else:# Use bash; the default is shp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, executable="/bin/bash")# the Popen() instance starts running once instantiated (??)# additionally, communicate(), or poll() and wait process to terminate# communicate() accepts optional input as stdin to the pipe (requires setting stdin=subprocess.PIPE above), return out, err as tuple# if communicate(), the results are buffered in memory# Read stdout from subprocess until the buffer is empty !# if error occurs, the stdout is '', which means the below loop is essentially skipped# A prefix of 'b' or 'B' is ignored in Python 2; # it indicates that the literal should become a bytes literal in Python 3 # (e.g. when code is automatically converted with 2to3).# return iter(p.stdout.readline, b'')for line in iter(p.stdout.readline, b''):# # Windows has \r\n, Unix has \n, Old mac has \r# if line not in ['','\n','\r','\r\n']: # Don't print blank linesyield linewhile p.poll() is None: sleep(.1) #Don't waste CPU-cycles# Empty STDERR buffererr = p.stderr.read()if p.returncode != 0:# responsible for logging STDERR print("Error: " + str(err))yield Noneout = []for line in _execute_cmd(cmd):# error did not occur earlierif line is not None:# trailing comma to avoid a newline (by print itself) being printedif output: print line,out.append(line.strip())else:# error occured earlierout = Nonereturn out
else:print "Simulation! The command is " + cmdprint ""
#9楼
像这样:
def runProcess(exe): p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)while(True):# returns None while subprocess is runningretcode = p.poll() line = p.stdout.readline()yield lineif retcode is not None:break
请注意,我正在将stderr重定向到stdout,它可能并非您想要的,但我也想要错误消息。
此函数逐行产生 (通常,您必须等待子进程完成才能获得整体输出)。
对于您的情况,用法是:
for line in runProcess('mysqladmin create test -uroot -pmysqladmin12'.split()):print line,
#10楼
这个问题的答案取决于您使用的Python版本。 最简单的方法是使用subprocess.check_output
函数:
>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
check_output
运行一个仅将参数作为输入的程序。 1它返回与打印到stdout
完全相同的结果。 如果需要将输入写入stdin
,请跳至run
或Popen
部分。 如果要执行复杂的Shell命令,请参阅此答案末尾关于shell=True
的注释。
check_output
函数可用于几乎所有仍在广泛使用的Python版本(2.7+)。 2但对于较新的版本,不再推荐使用此方法。
现代版本的Python(3.5或更高版本): run
如果您使用的是Python 3.5或更高版本,并且不需要向后兼容 ,则建议使用新的run
函数 。 它为subprocess
模块提供了非常通用的高级API。 要捕获程序的输出,请将subprocess.PIPE
标志传递给stdout
关键字参数。 然后访问返回的CompletedProcess
对象的stdout
属性:
>>> import subprocess
>>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> result.stdout
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
返回值是一个bytes
对象,因此,如果要使用正确的字符串,则需要对其进行decode
。 假设被调用的进程返回一个UTF-8编码的字符串:
>>> result.stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
所有这些都可以压缩为单线:
>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
如果要将输入传递给进程的stdin
,请将bytes
对象传递给input
关键字参数:
>>> cmd = ['awk', 'length($0) > 5']
>>> input = 'foo\nfoofoo\n'.encode('utf-8')
>>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=input)
>>> result.stdout.decode('utf-8')
'foofoo\n'
您可以通过传递stderr=subprocess.PIPE
(捕获到result.stderr
)或stderr=subprocess.STDOUT
(捕获到result.stdout
以及常规输出)来捕获错误。 如果不考虑安全性,您还可以通过传递shell=True
来运行更复杂的Shell命令,如下面的注释所述。
与旧的处理方式相比,这仅增加了一点复杂性。 但是我认为值得这样做:现在,您run
功能就可以完成几乎所有需要做的事情。
旧版本的Python(2.7-3.4): check_output
如果您使用的是旧版本的Python,或者需要适度的向后兼容性,则可以使用如上文所述的check_output
函数。 自python 2.7开始提供。
subprocess.check_output(*popenargs, **kwargs)
它采用与Popen
相同的参数(请参见下文),并返回一个包含程序输出的字符串。 该答案的开头有一个更详细的用法示例。 在Python 3.5及更高版本中, check_output
等效于使用check=True
和stdout=PIPE
执行run
,并仅返回stdout
属性。
您可以传递stderr=subprocess.STDOUT
以确保错误消息包含在返回的输出中-但是在某些版本的Python中,将stderr=subprocess.PIPE
check_output
传递给check_output
可能导致死锁 。 如果不考虑安全性,您还可以通过传递shell=True
来运行更复杂的Shell命令,如下面的注释所述。
如果您需要从stderr
进行管道传输或将输入传递给进程,则check_output
将无法完成任务。 在这种情况下,请参见下面的Popen
示例。
复杂的应用程序和Python的旧版(2.6及更低版本): Popen
如果需要深度向后兼容性,或者需要比check_output
提供的功能更复杂的功能,则必须直接使用Popen
对象,该对象封装了用于子流程的低级API。
Popen
构造函数可以接受不带参数的单个命令 ,也可以接受包含命令的列表作为其第一项,后跟任意数量的参数,每个参数均作为列表中的单独项。 shlex.split
可以帮助将字符串解析为适当格式的列表。 Popen
对象还接受用于进程IO管理和低级配置的许多不同参数 。
要发送输入和捕获输出, communicate
几乎总是首选方法。 如:
output = subprocess.Popen(["mycmd", "myarg"], stdout=subprocess.PIPE).communicate()[0]
要么
>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE,
... stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo
如果设置stdin=PIPE
,则communicate
还允许您通过stdin
将数据传递给流程:
>>> cmd = ['awk', 'length($0) > 5']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
... stderr=subprocess.PIPE,
... stdin=subprocess.PIPE)
>>> out, err = p.communicate('foo\nfoofoo\n')
>>> print out
foofoo
注意Aaron Hall的答案 ,它表明在某些系统上,您可能需要将stdout
, stderr
和stdin
全部设置为PIPE
(或DEVNULL
)才能使communicate
正常工作。
在极少数情况下,您可能需要复杂的实时输出捕获。 Vartec的答案提出了一条前进的道路,但如果不谨慎使用 ,则communicate
以外的方法很容易陷入僵局。
与上述所有功能一样,当不考虑安全性时,可以通过传递shell=True
来运行更复杂的Shell命令。
笔记
1.运行shell命令: shell=True
参数
通常情况下,每次调用run
, check_output
,或Popen
构造函数执行一个程序 。 这意味着没有花哨的bash风格的管道。 如果要运行复杂的Shell命令,则可以传递shell=True
,这三个功能都支持。
但是,这样做会引起安全问题 。 如果您除了做轻量级脚本编写外,还不如分别调用每个进程,并将每个进程的输出作为输入通过
run(cmd, [stdout=etc...], input=other_output)
要么
Popen(cmd, [stdout=etc...]).communicate(other_output)
直接连接管道的诱惑力很强; 抵抗它。 否则,您很可能会遇到僵局,或者不得不做类似此类的骇人听闻的事情。
2. Unicode注意事项
check_output
在Python 2中返回一个字符串,但在Python 3中返回一个bytes
对象。如果您还没有时间学习unicode,那么值得花一点时间。
#11楼
为subprocess
拆分初始命令可能很棘手且麻烦。
使用shlex.split()
帮助自己。
样例命令
git log -n 5 --since "5 years ago" --until "2 year ago"
编码
from subprocess import check_output
from shlex import splitres = check_output(split('git log -n 5 --since "5 years ago" --until "2 year ago"'))
print(res)
>>> b'commit 7696ab087a163e084d6870bb4e5e4d4198bdc61a\nAuthor: Artur Barseghyan...'
没有shlex.split()
,代码将如下所示
res = check_output(['git', 'log', '-n', '5', '--since', '5 years ago', '--until', '2 year ago'
])
print(res)
>>> b'commit 7696ab087a163e084d6870bb4e5e4d4198bdc61a\nAuthor: Artur Barseghyan...'
#12楼
根据@senderle,如果您像我一样使用python3.6:
def sh(cmd, input=""):rst = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, input=input.encode("utf-8"))assert rst.returncode == 0, rst.stderr.decode("utf-8")return rst.stdout.decode("utf-8")
sh("ls -a")
就像您在bash中运行命令一样
#13楼
如果使用subprocess
python模块,则可以分别处理STDOUT,STDERR和命令的返回代码。 您可以看到完整的命令调用程序实现的示例。 当然,您可以使用try..except
扩展它, try..except
需要。
下面的函数返回STDOUT,STDERR和Return代码,因此您可以在其他脚本中处理它们。
import subprocessdef command_caller(command=None)sp = subprocess.Popen(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=False)out, err = sp.communicate()if sp.returncode:print("Return code: %(ret_code)s Error message: %(err_msg)s"% {"ret_code": sp.returncode, "err_msg": err})return sp.returncode, out, err
#14楼
可以将输出重定向到文本文件,然后将其读回。
import subprocess
import os
import tempfiledef execute_to_file(command):"""This function execute the commandand pass its output to a tempfile then read it backIt is usefull for process that deploy child process"""temp_file = tempfile.NamedTemporaryFile(delete=False)temp_file.close()path = temp_file.namecommand = command + " > " + pathproc = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)if proc.stderr:# if command failed returnos.unlink(path)returnwith open(path, 'r') as f:data = f.read()os.unlink(path)return dataif __name__ == "__main__":path = "Somepath"command = 'ecls.exe /files ' + pathprint(execute(command))
#15楼
这很容易,但仅适用于Unix(包括Cygwin)和Python2.7。
import commands
print commands.getstatusoutput('wc -l file')
它返回带有(return_value,output)的元组。
对于在这两个Python2和Python3有效的解决方案,使用subprocess
模块来代替:
from subprocess import Popen, PIPE
output = Popen(["date"],stdout=PIPE)
response = output.communicate()
print response
运行shell命令并捕获输出相关推荐
- python执行shell命令查看输出_python 运行 shell 命令并捕获输出_python_酷徒编程知识库...
这个问题的答案取决于你使用的python 版本. 最简单的方法是使用 subprocess.check_output 函数:>>> subprocess.check_output([ ...
- python调用linux命令输出结果,Python-运行shell命令并捕获输出
小编典典 这个问题的答案取决于你使用的Python版本.最简单的方法是使用以下subprocess.check_output功能: >>> subprocess.check_outp ...
- python 3.7.3 shell_Python 3 运行 shell 命令
#python 3.5 , win10 引入包 #os.chdir('path') import os import subprocess #https://docs.python.org/3.5/l ...
- Python 标准库之 os (获取当前目录、读取/设置环境变量、重命名文件、运行shell命令、创建/删除/查看目录文件、判断目录/文件/存在、获取绝对路径、获取文件名、获取换行符、获取路径分隔符)
1. os与sys模块的官方解释如下: os This module provides a portable way of using operating system dependent funct ...
- 解决 Jupyter notebook 运行SHELL 命令(!xxx), 出错: OSError: “/bin/bach“ shell not found
我在JUPYTER NOTEBOOK新增加一个环境ai, 进入后,在NOTEBOOK的代码行中运行 SHELL 命令 (!pip install gradio) 出错: import os os.en ...
- python脚本运行命令_从Python脚本运行shell命令
我正在尝试从 python脚本中运行一个shell命令,它需要做几件事 1. shell命令是'hspice tran.deck>! tran.lis' 2.在继续之前,脚本应该等待shell命 ...
- php 运行 shell命令行参数,PHP exec()在通过浏览器执行时不会执行shell命令
我有一个PHP脚本,调用exec()执行一个命令,将PDF转换为JPG.此命令在bash中工作正常. 要抢占您的初始故障排除猜测,请注意以下事项: > safe_mode = Off >包 ...
- 将shell命令结果直接输出到HDFS上
直接将shell命令结果输出到HDFS echo "hehe" | hdfs dfs -put - /user/root/output.txt Hadoop shell命令大全: ...
- php实现linux命令,PHP在Linux下运行Shell命令
原本在本机开发PHP的时候,Shell调用一切正常.上线的时候才反应到线上的服务器对权限做了严格的控制,一顿折腾之后梳理出在严格权限控制的Linux上如何通过Nginx/Apache 以Web的方式调 ...
最新文章
- Java怎么测并发量_如何测试一个web网站的性能(并发数)?
- ubuntu修改环境变量
- Py之GUI之PyQt:PyQt5的简介、入门、安装(QtCreator和QtDesigner)图文教程之详细攻略
- 无失真压缩法可以减少冗余_混音笔记(七)——压缩器(2)压缩器参数调节方法...
- leetcode300. 最长递增子序列
- cocos2dx基础篇(26)——场景切换CCTransitionScene
- 饿了么监控系统 EMonitor 与美团点评 CAT 的对比
- 盘点当下稳定又好用的远程控制方案,软硬全覆盖
- 2019最新java实战项目资料
- TCN-时间卷积网络
- Multisim14 语言设置
- String类12个常用的方法
- java socket保活_gb28181简单实现sip信令服务器(java版基于springboot):四、sip摄像头心跳保活、推流(tcp/udp)和结束推流...
- Gin框架Go Web项目实战
- 轻松认识HTTP协议的概念和工作原理
- 一个非计算机专业的 软考中级 网络工程师考试之路
- matlab heart scale,libsvm-3.18 heart_scale文件格式错误
- 01-治疗脱发从MarkDown语法开始
- 基于springboot垃圾分类网站
- 【游戏通关】解题报告