我想编写一个函数,该函数将执行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楼

对于以下问题,我对同一问题的口味略有不同:

  1. 当STDOUT消息在STDOUT缓冲区中累积时(即实时)捕获并返回它们。

    • @vartec通过使用生成器和'yield'在Python上解决了这个问题
      上方关键字
  2. 打印所有STDOUT行( 即使在可以完全读取STDOUT缓冲区之前退出进程
  3. 不要浪费CPU周期以高频率轮询进程
  4. 检查子流程的返回码
  5. 如果获得非零错误返回码,则打印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平台:

  1. 无输出,但运行成功
  2. 输出空行,运行成功
  3. 运行失败
  4. 输出一些东西,成功运行

功能如下

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 ,请跳至runPopen部分。 如果要执行复杂的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=Truestdout=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的答案 ,它表明在某些系统上,您可能需要将stdoutstderrstdin全部设置为PIPE (或DEVNULL )才能使communicate正常工作。

在极少数情况下,您可能需要复杂的实时输出捕获。 Vartec的答案提出了一条前进的道路,但如果不谨慎使用 ,则communicate以外的方法很容易陷入僵局。

与上述所有功能一样,当不考虑安全性时,可以通过传递shell=True来运行更复杂的Shell命令。

笔记

1.运行shell命令: shell=True参数

通常情况下,每次调用runcheck_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命令并捕获输出相关推荐

  1. python执行shell命令查看输出_python 运行 shell 命令并捕获输出_python_酷徒编程知识库...

    这个问题的答案取决于你使用的python 版本. 最简单的方法是使用 subprocess.check_output 函数:>>> subprocess.check_output([ ...

  2. python调用linux命令输出结果,Python-运行shell命令并捕获输出

    小编典典 这个问题的答案取决于你使用的Python版本.最简单的方法是使用以下subprocess.check_output功能: >>> subprocess.check_outp ...

  3. 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 ...

  4. Python 标准库之 os (获取当前目录、读取/设置环境变量、重命名文件、运行shell命令、创建/删除/查看目录文件、判断目录/文件/存在、获取绝对路径、获取文件名、获取换行符、获取路径分隔符)

    1. os与sys模块的官方解释如下: os This module provides a portable way of using operating system dependent funct ...

  5. 解决 Jupyter notebook 运行SHELL 命令(!xxx), 出错: OSError: “/bin/bach“ shell not found

    我在JUPYTER NOTEBOOK新增加一个环境ai, 进入后,在NOTEBOOK的代码行中运行 SHELL 命令 (!pip install gradio) 出错: import os os.en ...

  6. python脚本运行命令_从Python脚本运行shell命令

    我正在尝试从 python脚本中运行一个shell命令,它需要做几件事 1. shell命令是'hspice tran.deck>! tran.lis' 2.在继续之前,脚本应该等待shell命 ...

  7. php 运行 shell命令行参数,PHP exec()在通过浏览器执行时不会执行shell命令

    我有一个PHP脚本,调用exec()执行一个命令,将PDF转换为JPG.此命令在bash中工作正常. 要抢占您的初始故障排除猜测,请注意以下事项: > safe_mode = Off >包 ...

  8. 将shell命令结果直接输出到HDFS上

    直接将shell命令结果输出到HDFS echo "hehe" | hdfs dfs -put - /user/root/output.txt Hadoop shell命令大全: ...

  9. php实现linux命令,PHP在Linux下运行Shell命令

    原本在本机开发PHP的时候,Shell调用一切正常.上线的时候才反应到线上的服务器对权限做了严格的控制,一顿折腾之后梳理出在严格权限控制的Linux上如何通过Nginx/Apache 以Web的方式调 ...

最新文章

  1. Java怎么测并发量_如何测试一个web网站的性能(并发数)?
  2. ubuntu修改环境变量
  3. Py之GUI之PyQt:PyQt5的简介、入门、安装(QtCreator和QtDesigner)图文教程之详细攻略
  4. 无失真压缩法可以减少冗余_混音笔记(七)——压缩器(2)压缩器参数调节方法...
  5. leetcode300. 最长递增子序列
  6. cocos2dx基础篇(26)——场景切换CCTransitionScene
  7. 饿了么监控系统 EMonitor 与美团点评 CAT 的对比
  8. 盘点当下稳定又好用的远程控制方案,软硬全覆盖
  9. 2019最新java实战项目资料
  10. TCN-时间卷积网络
  11. Multisim14 语言设置
  12. String类12个常用的方法
  13. java socket保活_gb28181简单实现sip信令服务器(java版基于springboot):四、sip摄像头心跳保活、推流(tcp/udp)和结束推流...
  14. Gin框架Go Web项目实战
  15. 轻松认识HTTP协议的概念和工作原理
  16. 一个非计算机专业的 软考中级 网络工程师考试之路
  17. matlab heart scale,libsvm-3.18 heart_scale文件格式错误
  18. 01-治疗脱发从MarkDown语法开始
  19. 基于springboot垃圾分类网站
  20. 【游戏通关】解题报告

热门文章

  1. 算法----合并两个有序链表
  2. A query was run and no Result Maps were found
  3. Hibernate配置详解
  4. 使用asm工具让移动设备投影到pc上
  5. 急速rust服务器管理_Rust 与服务端编程的碎碎念
  6. java websocket_理清 WebSocket 和 HTTP 的关系
  7. 安装搭建kafka集群
  8. java都界面相对布局_浏览器的重排和重绘
  9. 01:初识Redis
  10. 【bzoj 4764】弹飞大爷