运行shell命令并捕获输出


v-star*위위
2025-01-26 09:37:41 (26天前)
  1. 我想编写一个执行shell的函数


命令
</跨度>
并将其输出作为字符串返回,无论是错误还是成功消息。我只想得到与之相同的结果

命令
</跨度>
线。

什么是代码示例会做这样的事情?

例如:

def run_command(cmd):
#??????

print run_command(’mysqladmin create test -uroot -pmysqladmin12

9 条回复
  1. 0# 撩心 | 2019-08-31 10-32



    如果你需要在多个文件上运行shell命令,这对我来说就是这个诀窍。




    1. import os
      import subprocess

    2. Define a function for running commands and capturing stdout line by line

      (Modified from Vartecs solution because it wasnt printing all lines)

      def runProcess(exe):
      p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
      return iter(p.stdout.readline, b’’)

    3. Get all filenames in working directory

      for filename in os.listdir(‘./‘):

    4. # This command will be run on each file
    5. cmd = 'nm ' + filename
    6. # Run the command and capture the output line by line.
    7. for line in runProcess(cmd.split()):
    8.     # Eliminate leading and trailing whitespace
    9.     line.strip()
    10.     # Split the output 
    11.     output = line.split()
    12.     # Filter the output and print relevant lines
    13.     if len(output) > 2:
    14.         if ((output[2] == 'set_program_name')):
    15.             print filename
    16.             print line
    17. </code>


    编辑:刚刚看到马克斯佩尔森的解决方案与J.F.塞巴斯蒂安的建议。走在前面,并将其纳入其中。


  2. 1# 圈圈红 | 2019-08-31 10-32



    拆分初始命令

    subprocess

    可能是棘手和繁琐的。



    使用

    shlex.split

    帮助自己。




    示例命令
    </强>




    git log -n 5 —since “5 years ago” —until “2 year ago”




    代码
    </强>




    1. from subprocess import check_output
      from shlex import split

    2. res = check_output(split(‘git log -n 5 since 5 years ago until 2 year ago”‘))
      print(res)

    3. bcommit 7696ab087a163e084d6870bb4e5e4d4198bdc61a\nAuthor: Artur Barseghyan…’

    4. </code>

  3. 2# 不想吃东西 | 2019-08-31 10-32



    像这样的东西:




    1. def runProcess(exe):
      p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
      while(True):

    2.     # returns None while subprocess is running
    3.     retcode = p.poll() 
    4.     line = p.stdout.readline()
    5.     yield line
    6.     if retcode is not None:
    7.         break
    8. </code>


    注意,我正在将stderr重定向到stdout,它可能不是你想要的,但我也想要错误消息。



    这个功能

    随着它们的到来逐行产生
    </强>
    (通常你必须等待子进程完成以获得整个输出)。



    对于您的情况,用法将是:




    1. for line in runProcess(‘mysqladmin create test -uroot -pmysqladmin12’.split()):
      print line,

    2. </code>

  4. 3# نسر الصحراء | 2019-08-31 10-32



    我有同样的问题
    但想出了一个非常简单的方法
    按照这个




    1. import subprocess
      output = subprocess.getoutput(“ls -l”)
      print(output)

    2. </code>


    希望它有所帮助



    注意:此解决方案是特定于python3的

    subprocess.getoutput()

    不适用于python2


  5. 4# 故人 | 2019-08-31 10-32



    这样更容易,但只适用于Unix(包括Cygwin)。




    1. import commands
      print commands.getstatusoutput(‘wc -l file’)

    2. </code>


    它返回一个带有(return_value,output)的元组



    这只适用于

    python2.7

    :它不可用

    python3

    。对于兼容两者的解决方案,请使用

    subprocess

    模块改为:




    1. import subprocess
      output=subprocess.Popen([“date”],stdout=PIPE)
      response=output.communicate()
      print response

    2. </code>

  6. 5# 不丶离 | 2019-08-31 10-32



    现代Python解决方案(&gt; = 3.1):




    1. res = subprocess.check_output(lcmd, stderr=subprocess.STDOUT)

    2. </code>

  7. 6# 滔滔江水 | 2019-08-31 10-32



    例如,执行(’ls -ahl’)
    差异化的三/四种可能的回报和操作系统平台:




    1. 没有输出,但运行成功


    2. 输出空行,运行成功


    3. 运行失败


    4. 输出一些东西,运行成功

    5. </醇>


      功能如下




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

      2.     if error ocurs, returns None (ie, is None), print out the error message to screen
      3. “””
        if not DEBUG_MODE:
        print Command: + cmd

      4. # https://stackoverflow.com/a/40139101/2292993
      5. def _execute_cmd(cmd):
      6.     if os.name == 'nt' or platform.system() == 'Windows':
      7.         # set stdin, out, err all to PIPE to get results (other than None) after run the Popen() instance
      8.         p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
      9.     else:
      10.         # Use bash; the default is sh
      11.         p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, executable="/bin/bash")
      12.     # the Popen() instance starts running once instantiated (??)
      13.     # additionally, communicate(), or poll() and wait process to terminate
      14.     # communicate() accepts optional input as stdin to the pipe (requires setting stdin=subprocess.PIPE above), return out, err as tuple
      15.     # if communicate(), the results are buffered in memory
      16.     # Read stdout from subprocess until the buffer is empty !
      17.     # if error occurs, the stdout is '', which means the below loop is essentially skipped
      18.     # A prefix of 'b' or 'B' is ignored in Python 2; 
      19.     # it indicates that the literal should become a bytes literal in Python 3 
      20.     # (e.g. when code is automatically converted with 2to3).
      21.     # return iter(p.stdout.readline, b'')
      22.     for line in iter(p.stdout.readline, b''):
      23.         # # Windows has \r\n, Unix has \n, Old mac has \r
      24.         # if line not in ['','\n','\r','\r\n']: # Don't print blank lines
      25.             yield line
      26.     while p.poll() is None:                                                                                                                                        
      27.         sleep(.1) #Don't waste CPU-cycles
      28.     # Empty STDERR buffer
      29.     err = p.stderr.read()
      30.     if p.returncode != 0:
      31.         # responsible for logging STDERR 
      32.         print("Error: " + str(err))
      33.         yield None
      34. out = []
      35. for line in _execute_cmd(cmd):
      36.     # error did not occur earlier
      37.     if line is not None:
      38.         # trailing comma to avoid a newline (by print itself) being printed
      39.         if output: print line,
      40.         out.append(line.strip())
      41.     else:
      42.         # error occured earlier
      43.         out = None
      44. return out
      45. else:
        print Simulation! The command is + cmd
        print “”

      46. </code>

  8. 7# 咿呀哟 | 2019-08-31 10-32




    我对以下要求的问题略有不同:
    </强>




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

      1. <UL>
      2. <LI>
      3. <EM>
      4. @vartec通过使用生成器和'yield'来解决这个问题
      5. <BR/>

      以上关键字





    2. 打印所有STDOUT线(

      即使进程退出也可以完全读取STDOUT缓冲区




    3. 不要浪费CPU周期以高频率轮询过程


    4. 检查子进程的返回码


    5. 如果我们得到非零错误返回码,则打印STDERR(与STDOUT分开)。

    6. </醇>



      我结合并调整了以前的答案,得出以下结论:
      </强>




      1. import subprocess
        from time import sleep

      2. def run_command(command):
        p = subprocess.Popen(command,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        shell=True)

      3. # Read stdout from subprocess until the buffer is empty !
      4. for line in iter(p.stdout.readline, b''):
      5.     if line: # Don't print blank lines
      6.         yield line
      7. # This ensures the process has completed, AND sets the 'returncode' attr
      8. while p.poll() is None:                                                                                                                                        
      9.     sleep(.1) #Don't waste CPU-cycles
      10. # Empty STDERR buffer
      11. err = p.stderr.read()
      12. if p.returncode != 0:
      13.    # The run_command() function is responsible for logging STDERR 
      14.    print("Error: " + str(err))
      15. </code>



      此代码将与先前的答案执行相同:
      </强>




      1. for line in run_command(cmd):
        print(line)

      2. </code>

登录 后才能参与评论