У меня был немного другой вкус той же проблемы со следующими требованиями:
Я объединил и изменил предыдущие ответы, чтобы придумать следующее:
import subprocess
from time import sleep
def 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 lines
yield line
# This ensures the process has completed, AND sets the 'returncode' attr
while p.poll() is None:
sleep(.1) #Don't waste CPU-cycles
# Empty STDERR buffer
err = 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)
Ваш пробег мая может, я попытался использовать @ senderle в решении Vartec в Windows на Python 2.6.5, но я получал ошибки, и никаких других решений не работало. Моя ошибка: WindowsError: [Error 6] The handle is invalid
.
Я обнаружил, что мне пришлось назначить PIPE каждому дескриптору, чтобы он возвращал результат, который я ожидал, - для меня это работало.
import subprocess
def 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')
Что-то вроде этого:
def runProcess(exe):
p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while(True):
retcode = p.poll() #returns None while subprocess is running
line = p.stdout.readline()
yield line
if(retcode is not None):
break
Обратите внимание, что я перенаправляю stderr в stdout, это может быть не совсем то, что вы хотите, но я также хочу сообщения об ошибках.
Эта функция выводит строку за строкой по мере их поступления (обычно вам придется подождать завершения подпроцесса, чтобы получить результат в целом).
В вашем случае это будет:
for line in runProcess('mysqladmin create test -uroot -pmysqladmin12'.split()):
print line,
В Python 3.5:
import subprocess
output = subprocess.run("ls -l", shell=True, stdout=subprocess.PIPE,
universal_newlines=True)
print(output.stdout)
Если вам нужно запустить команду оболочки для нескольких файлов, это сделало трюк для меня.
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 file
cmd = 'nm ' + filename
# Run the command and capture the output line by line.
for line in runProcess(cmd.split()):
# Eliminate leading and trailing whitespace
line.strip()
# Split the output
output = line.split()
# Filter the output and print relevant lines
if len(output) > 2:
if ((output[2] == 'set_program_name')):
print filename
print line
Изменить: просто увидел решение Макса Перссона с предложением Я. Ф. Себастьяна. Пошел вперед и включил это.
У меня была та же проблема. Но выяснилось, что это очень просто:
import subprocess
Input = subprocess.getoutput("ls -l")
print(Input)
Надеюсь, что это поможет
Примечание: Это решение является специфичным для python3 как subprocess.getoutput()
не работают в python2
, например, execute ('ls -ahl') дифференцировал три / четыре возможных возврата и платформы ОС:
ниже
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 output
could be
[], ie, len()=0 --> no output;
[''] --> output empty line;
None --> error occured, see below
if 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/2292993
def _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() instance
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
else:
# Use bash; the default is sh
p = 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 lines
yield line
while p.poll() is None:
sleep(.1) #Don't waste CPU-cycles
# Empty STDERR buffer
err = p.stderr.read()
if p.returncode != 0:
# responsible for logging STDERR
print("Error: " + str(err))
yield None
out = []
for line in _execute_cmd(cmd):
# error did not occur earlier
if line is not None:
# trailing comma to avoid a newline (by print itself) being printed
if output: print line,
out.append(line.strip())
else:
# error occured earlier
out = None
return out
else:
print "Simulation! The command is " + cmd
print ""
Это сложное, но очень простое решение, которое работает во многих ситуациях:
import os
os.system('sample_cmd > tmp')
print open('tmp', 'r').read()
Временной файл (здесь tmp) создается с выходом команды, и вы можете прочитать с него желаемый выход.
Замечание из комментариев: вы можете удалить файл tmp в случае одноразового задания. Если вам нужно сделать это несколько раз, нет необходимости удалять tmp.
os.remove('tmp')
Вы можете использовать следующие команды для запуска любой команды оболочки. Я использовал их на ubuntu.
import os
os.popen('your command here').read()
Это проще, но работает только с Unix (включая Cygwin).
import commands
print commands.getstatusoutput('wc -l file')
возвращает кортеж с (return_value, output)
Современное решение Python (> = 3.1):
res = subprocess.check_output(lcmd, stderr=subprocess.STDOUT)