2016-10-03 65 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創建被保證是唯一的

相關問題