我有以下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
也无法解决问题。我也尝试在循环中进行睡眠,看看是否有帮助,但没有。
更新
我看到的一个有趣的行为:如果我ctrl+c
它,通常程序一直在运行 - try / except只捕获KeyboardInterrupt
并且它保持循环。但是,如果我ctr+c
发送错误后,程序退出,我得到以下内容。它几乎就像它在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 :(得分: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