2012-11-29 33 views
4

我在這個網站上發現了一個問題,它向我展示瞭如何從Python調用Perl腳本。我目前使用下面的代碼行來實現這一目標:從Python調用Perl腳本不斷返回值

pipe = subprocess.Popen(["perl", "./Perl_Script.pl", param], stdout=subprocess.PIPE) 
result = pipe.stdout.read() 

此作品完美,但唯一的問題是,Perl腳本需要幾分鐘的時間來運行。在Perl腳本的結尾處,我使用一條簡單的print語句來打印我需要返回的Python值,Python將其設置爲Python中的結果結果

有沒有辦法讓我的Perl腳本每隔幾秒就可以包含更多的打印語句,可以連續返回到Python(而不是等待幾分鐘,並在最後返回一個長列表)?

最終,我在做的是使用Perl腳本來獲取數據點,然後我發回到Python來繪製眼圖。當Perl腳本完成運行時,我不想等待幾分鐘來繪製眼圖,而是希望將數據段連續返回給Python,以便每隔幾秒更新一次。

+0

您是否嘗試過在perl腳本的中間階段進行簡單打印?我不明白問題是什麼。 –

+0

是的,但python變量_result_不會更新,直到perl腳本完成運行。是的,我可以在perl腳本中放置更多的打印語句,並且這些語句會返回 - 但是當perl腳本完成時,它們會一起返回。 – dmranck

+0

下面有一個關於在推送到管道時關閉緩衝的答案,另一個關於確保你沒有緩衝管道輸入的答案。你需要做這兩件事。 –

回答

1

你需要兩件:要在Python的空間一次讀取線和從Perl的一次發出一條線。第一可與環路來實現像

while True: 
    result = pipe.stdout.readline() 
    if not result: 
    break 
    # do something with result 

readline塊,直到文本的行(或EOF)從附接的過程中接收,然後給你它讀出的數據。只要每一塊數據都在自己的路線上,那就應該有效。

但是,如果您在不修改Perl腳本的情況下運行此代碼,您將不會獲得任何輸出,直到Perl腳本完成執行。這是因爲默認情況下,Perl將塊緩衝區輸出到管道。你可以告訴它通過在你打印範圍改變一個全局變量更頻繁刷新緩衝區:

use English qw(-no_match_vars); 
local $OUTPUT_AUTOFLUSH = 1; 
print ...; 

http://perl.plover.com/FAQs/Buffering.htmlhttp://perldoc.perl.org/perlvar.html

+0

謝謝!正是我需要的。 – dmranck

2

默認的UNIX stdio緩衝區至少爲8k。如果你寫的小於8k,你最終會等到程序結束之前緩衝區被刷新。

告訴Perl程序停止緩衝輸出,並可能告訴python不要通過管道緩衝輸入。

$| = 1;

到非緩衝器STDOUT在你的Perl程序。

+0

默認情況下大多數unix工具(處理文本)是否行緩存? '貓 - '顯示行爲(每一行都立即刷新)。 – goncalopp

+1

如果您直接使用read()和write()系統調用,則執行無緩衝輸出。如果使用stdio庫,則使用緩衝IO,因爲stdio在讀/寫之上實現緩衝。如果你想使用stdio函數,但沒有緩衝,你必須使用函數調用來設置緩衝區的大小爲0.我不知道cat是如何實現的,但stdio不像緩衝,但是提供了幾個面向行的功能。但是一行被定義爲一串文本,直到下一次出現行分隔符(在UNIX上默認爲\ n,在Windows上默認爲\ r \ n)。 –

+0

默認情況下,Perl對管道的STDOUT被塊緩衝。請參閱http://perldoc.perl.org/perlvar.html中的$ OUTPUT_AUTOFLUSH。 – darch

1

pipe.stdout.read()嘗試讀取整個流,因此它將阻塞,直到perl完成。 試試這個:

line=' ' 
while line: 
    line = pipe.stdout.readline() 
    print line, 
+1

正確,但不完整。如果不解決用戶的緩衝區痛苦,這將無濟於事。 (見http://perl.plover.com/FAQs/Buffering.html) – darch

+0

'緩衝痛苦'需要成爲模因。 –