2016-10-03 101 views
1

我正在编写使用一些Perl脚本的Python脚本,但其中一个使用stdout,所以我必须在bash中使用重定向>将此输出写入文件。构建一个运行Perl脚本的Python脚本。如何重定向标准输出?

所有输入和输出文件都是文本文件。

# -*- coding: utf-8 -*- 
import subprocess 

filename = input("What the name of the input? ") 

#STAGE 1---------------------------------------------------------------------- 
subprocess.Popen(["perl", "run_esearch.pl", filename , 'result']) 

#STAGE 2---------------------------------------------------------------------- 
subprocess.Popen(["perl", "shrink.pl", 'result']) 
'''Here the input from stage one is "shrunk" to smaller file, but 
the output is printed to the console. Is it possible to write this out 
to a file in Python, so I can use it in stage 3? ''' 

#STAGE 3---------------------------------------------------------------------- 
subprocess.Popen(["perl", "shrink2.pl", 'stdoutfromstage2']) 
+0

是'中间文件shrink2.pl'能够直接从标准输入中读取,还是必须以文件名作为参数? (也就是说,你能从命令行运行'perl shrink.pl result | perl shrink2.pl'吗?) – chepner

+0

必须从cmd行中获取参数 –

回答

0

这里是你如何使用bash输出重定向到一个文件test.txt一个例子:

import subprocess 

#STAGE 2---------------------------------------------------------------------- 
subprocess.Popen(['bash', '-c', 'echo Hello > test.txt']) 

#STAGE 3---------------------------------------------------------------------- 
subprocess.Popen(['perl', '-nE', 'say $_', 'test.txt']) 
1

我会处理在Python文件:

link = "stage2output" 
subprocess.call(["perl", "run_esearch.pl", filename, "result"]) 
with open(link, "w") as f: 
    subprocess.call(["perl", "shrink.pl", "result"], stdout=f) 
subprocess.call(["perl", "shrink2.pl", link]) 

上关 - 只要shrink2.pl可以从标准输入读取文件名-

subprocess.call(["perl", "run_esearch.pl", filename, "result"]) 
p2 = subprocess.Popen(["perl", "shrink.pl", "result"], stdout=subprocess.PIPE) 
subprocess.call(["perl", "shrink2.pl", "-"], stdin=p2.stdin) 
+0

“/ dev/stdin”的文件名也可能工作(取决于在OS上以及是否shrink.pl'在其输入文件中搜索)。 – melpomene

+0

确实如此,但“ - ”方法实际上仅依靠'shrink2.pl'使用内置的'open'函数来打开文件。不过,关于“寻求”的评论是一个很好的观点。 – chepner

+0

'subprocess,call()'优先于'subprocess.Popen()'在这里很重要。仅仅是“打开一个过程往往是不够的;你也将负责等待,等等(这段代码也应该证明这一点),而更高层的'call'等封装程序在后台为你做这些事情。 – tripleee

2

据我所知,你有三个Perl程序

  • run_esearch.pl,这需要两个命令行参数:输入文件名和名称,如果输出文件

  • shrink.pl,它需要一个命令行参数:输入文件的名称。它将其输出写入stdout

  • shrink2.pl,它需要一个命令行参数:输入文件的名称。你不说,关于它的输出

标准,并编写Linux程序最灵活的方式事情是让他们从stdin读写stdout。这样,输入和输出文件可以使用<>重定向在命令行上明确指定,或者可以使用相同的程序读取和写入管道|作为链的一部分。 Perl程序是两全其美的。使用空<>读取输入将收集作为命令行参数提到的文件的所有数据,或者如果没有参数将从stdin

我有没有办法知道哪条路你收缩程序对待自己输入,所以我必须想象最坏的情况:他们明确地打开并读取命令行中第一个参数指定的文件

Python的subprocess模块提供了Popen构造函数以及几个便利功能。通常不需要使用构造函数,特别是如果您默认大多数参数并丢弃返回的对象,那么我建议您通过构造函数,因为您将Python视为非常高级的shell,所以我建议您通过shell命令字符串设置为subprocess.callshell参数设置为True。这将允许您提供bash命令字符串,你会更熟悉地面等倍感控制

import subprocess 

filename = input("What's the name of the input? ") 

subprocess.call("perl run_esearch.pl %s result" % filename, shell=True) 

subprocess.call("perl shrink.pl result > shrink1_out", shell=True) 

subprocess.call("perl shrink2.pl shrink1_out", shell=True) 

注意,此方法是太冒险了在生产代码中使用,作为应对What the name of the input?可能包含可能危害您的系统的恶意shell代码。但是如果使用你的程序的人如果选择的话就可以直接破坏你的系统,那么不会丢失任何东西

另一个问题是固定名称用于中间文件。 无法保证独立的独立进程不会使用具有相同路径的文件,因此理论上这个过程是不安全的。 我跟着你的领导,并使用resultrun_esearch.pl输出,并发明shrink1_outshrink.pl输出,而是一个适当的程序将使用tempfile模块,并调用tempfile.NamedTemporaryFile创建被保证是唯一的

相关问题