1

假设一个 python 脚本可以调用:

python myscript.py ./mycommand > myoutput.txt

如何确保myscript.py获取./mycommand > myoutput.txt命令行参数列表,而不是 shell 将输出管道python myscript.py ./mycommand传输到文件?

编辑

使用引号会带来额外的问题。考虑:

import subprocess
import sys

argList = sys.argv[1].split()

subprocess.call(argList)

然后由以下方式调用:

python myscript.py 'ls -l > ls.out'

结果是

ls: cannot access >: No such file or directory
ls: cannot access ls.out: No such file or directory

动机是只有我试图运行的命令的输出应该保存在文件中。myscript.pyto的任何其他输出stdout都不应该进入文件。看起来管道需要设置stdoutsubprocess.call(). >有没有办法直接使用参数列表,这样我就不必为之类的东西解析2>它?2&><

4

2 回答 2

3

如果您愿意承担依赖关系,您可以使用Kenneth Reitz 的envoy(如果您想从命令行将任意命令传递给您的脚本,您仍然需要使用引号)。

from envoy import run
from sys import argv

run(argv[1])

然后您可以使用以下方法调用它:

$ python myscript.py './mycommand > myoutput.txt'

或者,如果您想在 Python 文件中使用类似 shell 的语法,您可以使用sh(以前pbs)或plumbum

from sh import ls

with open("myoutput.txt", "w") as outfile:
    ls("-l", _out=outfile)

# Or, in plumbum
from plumbum.cmd import ls

# Yes, this looks crazy, but the docs say it works.
ls["-l"] > "myoutput.txt"
于 2012-10-02T02:09:26.257 回答
2

标准 bash 或 tcsh shell 将解析您给它的命令,并将某些特殊字符解释为 shell 进程本身的方向(示例中的“>”字符)。被调用的程序对此没有控制权;命令行解析发生在你的程序被调用之前。

在您的示例中,您可以说:

python myscript.py ./mycommand ">" myoutput.txt

引用的 ">" 将告诉 shell 不要使用它的特殊行为。

子进程模块有两种操作模式;一个带有 shell(通常是 /bin/sh)的中间过程——这是你给Popen对象一个shell=True关键字参数的时候。当您以这种方式调用它时,它会调用 shell 来解析参数文本,然后 shell 调用您指定为从程序中删除的子进程的命令。

另一种操作模式,默认,是 when shell=False。这将创建一个子进程并直接填充其 ARGV 数组,而无需任何中间 shell 尝试解释命令中的字符。

最终结果是,如果您想从解释特殊字符并包含特殊字符的 shell 发出命令,您必须对它们进行转义或引用它们。如果您从subprocess标准库模块调用子进程,则可以传入任意文本作为子进程的 ARGV 元素,而不必担心它们会被中间 shell 进程以某种特殊方式解释。

于 2012-10-02T01:59:42.113 回答