在bash中考虑以下命令:
multi-bleu.perl reference < mt-output
我有两个问题:
reference
和mt-output
不是参数,但它们以某种方式写入stdin
。因此,如果它们是文件,它们的内容是否会写入stdin
?我的尝试不起作用。包含在文件test.py
中:
from subprocess import Popen, PIPE
import settings
command = settings.BLEU + " " + settings.CORPUS + " < " + settings.HYPOTHESIS
print command
pipe = Popen(command, stdin=PIPE, stdout=PIPE)
output = pipe.communicate()[0]
print output
我运行与运行test.py
相同的文件夹中打印的命令。前者是作品,后者则不是。错误回溯如下:
Traceback (most recent call last):
File "/Users/[...]/tests.py", line 6, in <module>
pipe = Popen([command], stdin=PIPE, stdout=PIPE)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 711, in __init__
errread, errwrite)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 1308, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
答案 0 :(得分:3)
你的bash / perl示例会发生什么取决于perl脚本正在做什么。有关bash方面发生的事情的解释,请参阅以下内容:
[sugarcube->temp]echo "Foo" > foo
[sugarcube->temp]echo "Bar" > bar
[sugarcube->temp]cat foo < bar
Foo
[sugarcube->temp]cat foo
Foo
[sugarcube->temp]cat bar
Bar
[sugarcube->temp]cat foo - < bar
Foo
Bar
我在这里创建了两个文件foo
和bar
。 <
执行redirection of file contents to stdin。但是,在第一个cat
示例中,cat
没有获取(重定向文件的内容)bar
。 cat
需要一个显式参数-
,告诉它从stdin读取输入。
因此,在您的示例中,reference
只是perl脚本的一个参数(可能只是将其作为文件打开)。 mt-output
的内容被重定向到stdin,因此如果Perl脚本从stdin读取,它将处理它。
如果你想在Python中实现类似的东西,你的Python脚本只需要打开它接收的任何文件作为它的第一个参数(你可能要考虑argparse对命令行程序进行常规参数解析,虽然这个特殊问题可能有点过分了)。要处理来自stdin的数据,只需从sys.stdin读取。
答案 1 :(得分:3)
reference
确实是一个正常的命令行参数;它的语义取决于被调用的程序。它可能是文件名(输入或输出),命令或其他任何内容。
现在,有两种方法可以调用Popen()
:
shell=False
(默认值):
with open('mt-output', 'r') as infile:
pipe = Popen(['multi-bleu.perl', 'reference'], stdin=infile, stdout=PIPE)
RESP。
with open(settings.HYPOTHESIS, 'r') as infile:
pipe = Popen([settings.BLEU, settings.CORPUS], stdin=infile, stdout=PIPE)
在这里,您可以打开要自己阅读的文件,然后传递打开的文件,使其成为流程&#39;标准输入。
直接调用给定的文件。
shell=True
:
command = settings.BLEU + " " + settings.CORPUS + " < " + settings.HYPOTHESIS
pipe = Popen(command, stdout=PIPE)
在这里,您将所有操作都放在程序和要调用的程序之间的shel上。因此,您不会给出一个参数列表,而是一个命令行。
stdin重定向也由shell执行。
第二种解决方案可能看起来更简单,但根据settings
中的数据来源以及它们的外观,它可能非常危险。