2013-02-11 88 views
2

後,我有以下Python代碼:標準輸出將不刷新異常

import sys 
import traceback 
fifo_in = sys.argv[1] 
while 1: 
    try: 
    exec open(fifo_in) 
    except: 
    traceback.print_exc() 
    sys.stdout.flush() 

第一個參數是由mkfifo創建命名管道。所以下面打印'1':

mkfifo input 
python script.py input 

... in a separate terminal ... 

echo "print 1" > input 

很好,迄今爲止很好。但是當我執行類似echo "foobar" > input的操作時,該腳本僅打印部分的回溯。然後暫停,直到我發送另一個命令,並且輸出混合起來:

echo "asdf" > input # pause here and check output 
echo "print 1" > input 

... in output terminal ... 

Traceback (most recent call last): 
    File "test.py", line 8, in <module> 
    exec open(fifo_in) 
    File "in", line 1, in <module> 
...PAUSES HERE... 
    print 1 
NameError: name 'asdf' is not defined 

發生了什麼事?我怎樣才能讓stdout完全沖洗,爲什麼它沒有秩序?我試過用traceback.format_exc來代替,然後手工打印,但是我得到了相同的結果。調用sys.stderr.flush也不能解決任何問題。我也嘗試在循環中進行睡眠,看看是否有幫助,但沒有。

UPDATE

一個有趣的一件行爲我看到的:如果我ctrl+c它,正常程序繼續運行 - 在try /除了剛剛捕獲KeyboardInterrupt並不斷循環。但是,如果我在發送錯誤後發現它,程序退出,我得到以下信息。這幾乎就像是暫停的print_exc內:

^CTraceback (most recent call last): 
    File "test.py", line 10, in <module> 
    traceback.print_exc() 
    File "/usr/lib/python2.7/traceback.py", line 232, in print_exc 
    print_exception(etype, value, tb, limit, file) 
    File "/usr/lib/python2.7/traceback.py", line 125, in print_exception 
    print_tb(tb, limit, file) 
    File "/usr/lib/python2.7/traceback.py", line 69, in print_tb 
    line = linecache.getline(filename, lineno, f.f_globals) 
    File "/usr/lib/python2.7/linecache.py", line 14, in getline 
    lines = getlines(filename, module_globals) 
    File "/usr/lib/python2.7/linecache.py", line 40, in getlines 
    return updatecache(filename, module_globals) 
    File "/usr/lib/python2.7/linecache.py", line 132, in updatecache 
    with open(fullname, 'rU') as fp: 
KeyboardInterrupt 
+0

難道你不想在你的除了塊的沖洗? – 2013-02-11 19:50:28

+0

@HunterMcMillen無論代碼採用什麼路徑,我都希望它能夠刷新。在except塊內放置第二次沖洗似乎沒有幫助。 – 2013-02-11 19:52:41

+0

這可能值得在'finally'塊中用'flush'調用來嘗試。我不確定它是否適用於這種特殊情況,但我認爲這種情況是「終於」存在的原因之一。 – bernie 2013-02-11 19:55:11

回答

3

我想你想看看the stdlib code module

此行爲是使用EXEC。 Exec用於評估python代碼,所以「print 1」執行python代碼print 1,其中「asdf」將引發NameError,因爲它不存在於上下文中。 exec open(fifo_in)很奇怪,因爲它不應該工作。一會兒也會吃掉100%cpu。

更新:修復睡眠持續時間 這是您的代碼的嘗試修改版本。

import sys 
import time 
import traceback 
fifo_in = sys.argv[1] 
try: 
    fp = open(fifo_in) # will block until pipe is opened for write 
except IOError: 
    traceback.print_exc() 
except OSError: 
    traceback.print_exc() 

data = None 
while True: 
    try: 
     data = fp.read() 
     try: 
      exec data 
     except: 
      traceback.print_exc() 
     finally: 
      time.sleep(0.1) 
    except KeyboardInterrupt: 
     break 
+0

有趣的是,使用'fp.read'修復了它,但是根據Python的文檔:「第一個表達式應該評估爲字符串,_打開文件object_,[...]」。 http://docs.python.org/2/reference/simple_stmts.html#grammar-token-exec_stmt – 2013-02-11 22:06:27

+0

我認爲它是「如果它是一個打開的文件,該文件被解析,直到EOF並執行。」。執行者不會等待EOF永遠不會到來。 – jlujan 2013-02-11 22:13:59

+0

嗯。它確實運行。運行traceback.print_exc時它會卡住。非常奇怪的行爲。我認爲你是正確的,但這需要更多的調查。 – 2013-02-11 22:18:43