Python считывает данные из системной команды [duplicate]

608
задан Peter Mortensen 24 May 2015 в 01:11
поделиться

11 ответов

У меня был немного другой вкус той же проблемы со следующими требованиями:

  1. Захват и возврат сообщений STDOUT по мере их накопления в буфере STDOUT (т. е. в реальном времени). @vartec решил эту Pythonically с использованием генераторов и ключевым словом «yield» выше
  2. Распечатайте все строки STDOUT (, даже если процесс завершается до того, как буфер STDOUT может быть полностью прочитан )
  3. Не тратьте процессорные циклы на процесс на высокочастотном
  4. Проверьте код возврата подпроцесса
  5. Печать STDERR (раздельно из STDOUT), если мы получим ненулевой код возврата ошибки.

Я объединил и изменил предыдущие ответы, чтобы придумать следующее:

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)
724
ответ дан Community 4 September 2018 в 07:35
поделиться

Ваш пробег мая может, я попытался использовать @ 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')
9
ответ дан Aaron Hall 4 September 2018 в 07:35
поделиться

Что-то вроде этого:

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,
97
ответ дан Anders 4 September 2018 в 07:35
поделиться

В Python 3.5:

import subprocess

output = subprocess.run("ls -l", shell=True, stdout=subprocess.PIPE, 
                        universal_newlines=True)
print(output.stdout)
13
ответ дан cmlaverdiere 4 September 2018 в 07:35
поделиться

Если вам нужно запустить команду оболочки для нескольких файлов, это сделало трюк для меня.

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

Изменить: просто увидел решение Макса Перссона с предложением Я. Ф. Себастьяна. Пошел вперед и включил это.

2
ответ дан Ethan Strider 4 September 2018 в 07:35
поделиться

У меня была та же проблема. Но выяснилось, что это очень просто:

import subprocess
Input = subprocess.getoutput("ls -l")
print(Input)

Надеюсь, что это поможет

Примечание: Это решение является специфичным для python3 как subprocess.getoutput() не работают в python2

9
ответ дан itz-azhar 4 September 2018 в 07:35
поделиться

, например, execute ('ls -ahl') дифференцировал три / четыре возможных возврата и платформы ОС:

  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 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 ""
0
ответ дан Jerry T 4 September 2018 в 07:35
поделиться

Это сложное, но очень простое решение, которое работает во многих ситуациях:

import os
os.system('sample_cmd > tmp')
print open('tmp', 'r').read()

Временной файл (здесь tmp) создается с выходом команды, и вы можете прочитать с него желаемый выход.

Замечание из комментариев: вы можете удалить файл tmp в случае одноразового задания. Если вам нужно сделать это несколько раз, нет необходимости удалять tmp.

os.remove('tmp')
36
ответ дан Mehdi1902 4 September 2018 в 07:35
поделиться

Вы можете использовать следующие команды для запуска любой команды оболочки. Я использовал их на ubuntu.

import os
os.popen('your command here').read()
11
ответ дан Muhammad Hassan 4 September 2018 в 07:35
поделиться

Это проще, но работает только с Unix (включая Cygwin).

import commands
print commands.getstatusoutput('wc -l file')

возвращает кортеж с (return_value, output)

172
ответ дан rogerdpack 4 September 2018 в 07:35
поделиться

Современное решение Python (> = 3.1):

 res = subprocess.check_output(lcmd, stderr=subprocess.STDOUT)
13
ответ дан zlr 4 September 2018 в 07:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: