babel python check_output 错误非零退出状态 2

babel python check_output error non-zero exit status 2

在 python 中,我有一行:

check_output(['babel', 'www/scripts6/lib/data.js', '>', 'www/scripts/lib/data.js'])

它给我错误:

subprocess.CalledProcessError: Command '['babel', 'www/scripts6/lib/data.js', '>', 'www/scripts/lib/data.js']' returned non-zero exit status 2

我被难住了。该命令在 shell 中运行良好。为什么 python 抱怨?

编辑:使用

print(check_output(['babel', './www/scripts6/lib/data.js', '>', './www/scripts/lib/data.js'], shell=True))

而是产生输出

b'"use strict";\n\n'

在终端中。这表明 babel 现在正在工作,但 babel 正在接收 NOTHING 作为其输入并输出到终端。

我怀疑您需要输入 babel 的完整路径,而不仅仅是 babel,但您可以尝试以下操作,看看是否有所不同:

check_output(['babel', 'www/scripts6/lib/data.js', '>', 'www/scripts/lib/data.js'], shell=True)

EDIT: 参考您的编辑,我们使用 subprocess.Popen():

而不是 check_output
import shlex
from subprocess import Popen

with open('./www/scripts/lib/data.js', 'w') as outfile:
    command = "babel ./www/scripts6/lib/data.js"
    command_args = shlex.split(command)
    process = Popen(command_args, stdout=outfile, shell=True)
    output, err = process.communicate()
    if err:
        print err

您应该将 shell 命令作为单个字符串传递给 check_output。关于这个函数的 documentation 实际上给出了一个例子。在您的情况下,它看起来像这样:

check_output('path/to/babel ./www/scripts6/lib/data.js > '
             './www/scripts/lib/data.js', shell=True)

Popen 上的 documentation 指出:

On POSIX with shell=True, the shell defaults to /bin/sh. If args is a string, the string specifies the command to execute through the shell. This means that the string must be formatted exactly as it would be when typed at the shell prompt. This includes, for example, quoting or backslash escaping filenames with spaces in them. If args is a sequence, the first item specifies the command string, and any additional items will be treated as additional arguments to the shell itself. That is to say, Popen does the equivalent of:

Popen(['/bin/sh', '-c', args[0], args[1], ...])

check_outputshell=True 以与上述相同的方式解释其参数。

如果您使用 shell 只是为了重定向,我建议您改为这样做:

check_output(['path/to/babel', './www/scripts6/lib/data.js', 
              '--out-file', './www/scripts/lib/data.js'])

这会将输出保存到您想要的文件中,而无需生成 shell。

如前所述,您需要使用 shell=True,传递单个字符串以使您的代码正常工作,更简单的解决方案是使用 check_call,将文件对象传递给标准输出:

from subprocess import check_call

with open('./www/scripts/lib/data.js',"w") as f:    
    check_call(['babel', './www/scripts6/lib/data.js'],stdout=f)

如果您只是担心重定向输出那么我认为不需要 check_output 或任何其他存储任何输出的方法,您可能希望将代码包装在 try/except 虽然并捕获任何非零退出状态。您还可以设置 cwd:

from subprocess import check_call, CalledProcessError

def babel_sub(cmds, out_f, cwd="."):
    with open(out_f, "w") as f:
        try:
            check_call(cmds, stdout=f, cwd=cwd)
        except CalledProcessError as e:
            print(e)