2013-02-11 81 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