【问题标题】:Launch a shell command with in a python script, wait for the termination and return to the script在 python 脚本中启动 shell 命令,等待终止并返回脚本
【发布时间】:2010-09-24 10:31:09
【问题描述】:

我有一个 python 脚本,它必须为目录中的每个文件启动一个 shell 命令:

import os

files = os.listdir(".")
for f in files:
    os.execlp("myscript", "myscript", f)

这对第一个文件很好,但是在“myscript”命令结束后,执行停止并且不会返回到 python 脚本。

我该怎么办?我必须在calling os.execlp() 之前fork() 吗?

【问题讨论】:

标签: python subprocess popen os.execl


【解决方案1】:

子进程:subprocess 模块 允许您生成新进程, 连接到他们的输入/输出/错误 管道,并获取它们的返回码。

http://docs.python.org/library/subprocess.html

用法:

import subprocess
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
process.wait()
print process.returncode

【讨论】:

  • 我认为作为公认的答案,这应该包含至少与@Harley 相同数量的细节。这更多是个人要求,但我认为较新的文档更好地呈现信息。您能否改为链接到 2.7 版本的文档?
  • 较新版本的文档位于docs.python.org/library/subprocess.html
  • remove stdout=PIPE 如果子程序产生足够的输出(Linux 上大约 65KB),它可能会挂起脚本。 shell=True 是不必要的。
  • 如果没有 shell=True,它会在 python 2.7 上引发异常...文件“/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py”,第 1335 行,在 _execute_child raise child_exception OSError: [Errno 2] No such file or directory
【解决方案2】:

您可以使用subprocess.Popen。有几种方法可以做到:

import subprocess
cmd = ['/run/myscript', '--arg', 'value']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
for line in p.stdout:
    print line
p.wait()
print p.returncode

或者,如果您不关心外部程序实际做了什么:

cmd = ['/run/myscript', '--arg', 'value']
subprocess.Popen(cmd).wait()

【讨论】:

  • for line in p.stdout: 可能会由于预读而延迟一行的输出。您可以使用for line in iter(p.stdout.readline, b''): print line,(注意:最后的逗号)。去掉第二个例子中的stdout=PIPE;它可能会挂起脚本。或者如果您不需要非零返回代码的异常,则只需使用subprocess.call()
【解决方案3】:

自 2008 年以来,子流程模块已经出现。特别是 check_callcheck_output 使简单的子流程变得更加容易。 check_* 系列函数很不错,如果出现问题它们会引发异常。

import os
import subprocess

files = os.listdir('.')
for f in files:
   subprocess.check_call( [ 'myscript', f ] )

myscript 生成的任何输出都将显示为好像您的进程生成了输出(技术上myscript 和您的 python 脚本共享相同的标准输出)。有几种方法可以避免这种情况。

  • check_call( [ 'myscript', f ], stdout=subprocess.PIPE )
    标准输出将被抑制(注意myscript 是否产生超过 4k 的输出)。除非您添加选项 stderr=subprocess.PIPE,否则仍会显示 stderr。
  • check_output( [ 'myscript', f ] )
    check_output 将标准输出作为字符串返回,因此不显示。除非您添加选项 stderr=subprocess.STDOUT,否则仍会显示 stderr。

【讨论】:

  • @Luke Stanley:你的问题不清楚,但我会试一试。 subprocess.check_* 函数使调用外部二进制文件比手动使用 subprocess.Popen 更容易。特别是,您永远不需要处理wait()communicate()return_code 等。您也不必担心像悬空管道这样的问题会阻碍可执行文件。当涉及到与外部二进制文件交互时,check_* 函数并没有太大帮助,但对于大多数用例来说,结果更短,更不容易出错,也更容易。
  • 您可以使用 subprocess.DEVNULLopen(os.devnull, 'r+b') 来忽略输入/输出而不是 subprocess.PIPE 以避免可能的死锁
【解决方案4】:

os.exec*() 函数用新的程序替换当前程序。当这个程序结束时,您的进程也会结束。你可能想要os.system()

【讨论】:

  • os.system() 在安全性方面存在很大问题,以至于许多 C 库直接删除了这个标准 C 函数。应该使用 shell=False 的 subprocess.Popen() 来代替
【解决方案5】:

使用生成

import os
os.spawnlp(os.P_WAIT, 'cp', 'cp', 'index.html', '/dev/null')

【讨论】:

    【解决方案6】:

    我使用 os.system

    import os
    os.system("pdftoppm -png {} {}".format(path2pdf, os.path.join(tmpdirname, "temp")))
    

    【讨论】:

      【解决方案7】:

      这对我来说很好!

      shell_command = "ls -l" subprocess.call(shell_command.split())

      【讨论】:

        猜你喜欢
        • 2021-03-08
        • 1970-01-01
        • 2017-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-24
        • 1970-01-01
        相关资源
        最近更新 更多