def captureOutput(self, func, *args, **kwargs):
pass
sys.stdout.flush()
sys.stderr.flush()
(outfd, fn) = tempfile.mkstemp()
fout = os.fdopen(outfd, 'r')
os.unlink(fn)
(errfd, fn) = tempfile.mkstemp()
ferr = os.fdopen(errfd, 'r')
os.unlink(fn)
try:
oldstdout = os.dup(sys.stdout.fileno())
oldstderr = os.dup(sys.stderr.fileno())
os.dup2(outfd, sys.stdout.fileno())
os.dup2(errfd, sys.stderr.fileno())
try:
ret = func(*args, **kwargs)
finally:
sys.stderr.flush()
sys.stdout.flush()
os.dup2(oldstdout, sys.stdout.fileno())
os.close(oldstdout)
os.dup2(oldstderr, sys.stderr.fileno())
os.close(oldstderr)
os.lseek(outfd, 0, 0)
out = fout.read()
os.lseek(errfd, 0, 0)
err = ferr.read()
finally:
fout.close()
ferr.close()
return ret, out, err
Run Code Online (Sandbox Code Playgroud)
运行此代码时,出现错误:
AttributeError: StringIO instance has no attribute 'fileno'
为什么我会收到此错误,如何更正错误?
sam*_*ias 13
该fileno()方法未在StringIO中实现,因为它不是真实文件(因此没有关联的文件描述符).从来源:
- fileno() is left unimplemented so that code which uses it
triggers an exception early.
Run Code Online (Sandbox Code Playgroud)
可能有人sys.stdout用StringIO实例替换,以捕获输出.
例如,当我以这种方式运行您的代码时,我得到相同的异常:
from StringIO import StringIO
sys.stdout = StringIO()
captureOutput(testfunc)
Run Code Online (Sandbox Code Playgroud)
错误:
oldstdout = os.dup(sys.stdout.fileno())
AttributeError: StringIO instance has no attribute 'fileno'
Run Code Online (Sandbox Code Playgroud)
最好从头到尾跟踪代码,寻找sys.stdout被覆盖的点.这是我给出的另一个答案的链接,显示了如何通过跟踪活动来执行代码:
ares% python -m trace -c -t -C ./coverage test_sio.py | grep sys.stdout
test_sio.py(47): sys.stdout = StringIO()
Run Code Online (Sandbox Code Playgroud)
你使用标准的普通python解释器吗?当您使用覆盖stdout/stderr的解释器(例如IDLE)时可能会出现此错误(尽管IDLE本身会给您一个不同的错误).它也可能是由覆盖stdout/stderr的库引起的.
有时您可以通过写入将stdout重置为默认标准输出sys.stdout = sys.__stdout__,但不要指望它始终有效.例如,它在Pythonwin中不起作用.
无论如何,您尝试对代码执行的操作似乎是自己重定向stdout/stderr.如果是这样的话,你应该继续这样做.我认为这应该有效,如果你有文件描述符outfd和errfd:
sys.stdout = os.fdopen(outfd, 'w')
sys.stderr = os.fdopen(errfd, 'w')
Run Code Online (Sandbox Code Playgroud)
现在我可以看到您的整个代码,我根本不会使用临时文件.
def captureOutput(self, func, *args, **kwargs):
import cStringIO # You can also use StringIO instead
sys.stderr.flush()
sys.stdout.flush()
olderr, oldout = sys.stderr, sys.stdout
try:
sys.stderr = cStringIO.StringIO()
sys.stdout = cStringIO.StringIO()
try:
ret = func(*args, **kwargs)
finally:
stderr.seek(0)
stdout.seek(0)
err = stderr.read()
out = stdout.read()
finally:
sys.stderr = olderr
sys.stdout = oldout
return ret, out, err
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
21019 次 |
| 最近记录: |