Python AttributeError:StringIO实例没有属性';文件编号';
运行此代码时,我收到一个错误:Python AttributeError:StringIO实例没有属性';文件编号';,python,Python,运行此代码时,我收到一个错误: 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() fe
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
AttributeError:StringIO实例没有属性“fileno”
为什么会出现此错误以及如何更正它?StringIO中未实现fileno()
方法,因为它不是真实的文件(因此没有关联的文件描述符)。来源:
AttributeError: StringIO instance has no attribute 'fileno'
可能有人用StringIO实例替换了sys.stdout以捕获输出
例如,当我以这种方式运行代码时,会得到相同的异常:
- fileno() is left unimplemented so that code which uses it
triggers an exception early.
错误:
from StringIO import StringIO
sys.stdout = StringIO()
captureOutput(testfunc)
最好从头到尾跟踪代码,查找被覆盖的点
sys.stdout
。下面是一个示例,展示了如何在跟踪处于活动状态时执行代码:
oldstdout = os.dup(sys.stdout.fileno())
AttributeError: StringIO instance has no attribute 'fileno'
我猜可能是代码中的其他地方,sys.stdout或sys.stderr被重新分配为StringIO的实例。这段代码是在什么环境下运行的(比如在某个web框架内,从命令行执行)?这可能会给熟悉该环境的人提供正确答案的线索。您使用的是标准的纯python解释器吗?当您使用重写stdout/stderr的解释器时,例如IDLE(尽管IDLE本身会给您一个不同的错误),可能会出现此错误。它也可能是由重写stdout/stderr的库引起的 有时,您可以通过写入sys.stdout=sys.\uu stdout\uuu将标准输出重置为默认标准输出,但不要指望它总是工作。例如,它在蟒蛇身上不起作用 不管怎么说,似乎您试图对代码做的是自己重定向stdout/stderr。如果是这样的话,你应该继续做下去。如果您有文件描述符
outpd
和errfd
,我认为这应该是可行的:
ares% python -m trace -c -t -C ./coverage test_sio.py | grep sys.stdout
test_sio.py(47): sys.stdout = StringIO()
编辑:
现在我可以看到你的全部代码了,我根本不会使用临时文件
sys.stdout = os.fdopen(outfd, 'w')
sys.stderr = os.fdopen(errfd, 'w')
简而言之,您在标准库中遇到了一个bug。StringIO未履行其IOBase类的契约。某个类写入IOBase类接口,然后该接口失败 更具体地说,Subprocess.run()或其他一些函数使用IOBase fileno函数。子类StringIO引发此异常,因为它不是真正的子类。在某个地方,IOBase的许多用户中有一个失败了。记录StringIO无助于解决此问题
也许你可以围绕它编码。也许不是。像contextlib.redirectstdout()这样的所有函数都将失败。需要更多的代码,outpd和errfd是什么?您使用的是标准的纯python解释器吗?当您使用重写stdout/stderr的解释器时,例如IDLE(尽管IDLE本身会给您一个不同的错误),可能会出现此错误。这也可能是由重写stdout/stderr的库引起的。我找不到任何StringIO的导入,可能是因为使用了dup()和dup2()?这会导致错误吗?现在:dup()和dup2()解释如下:和返回文件描述符。dup(fd)返回文件描述符fd的副本。可用性:Unix、Windows。dup2(fd,fd2)将文件描述符fd复制到fd2,必要时先关闭后者。可用性:Unix、Windows。@kamal我不认为
dup()
会导致那个特定的错误。尝试访问缺少的[obj].fileno
属性时发生异常。您是否在IDE下运行?可能您的IDE是在StringIO中交换的,如另一个答案中所述。我不是在IDE中运行,而是在shell(bash)中运行,因此我有一个bash脚本使用nosetests@kamal试试Python跟踪器-我已经用更多细节更新了我的答案。这是非常好的信息,谢谢,但我相信在本例中,test_sio.py是可执行的(该行是否没有if name_uuu==''uuuu main')正确?在我的例子中,使用Python2.7.5是不正确的。。。函数cStringIO.getvalue()不是代替了csStringIO.read()吗?另外,您不应该关闭cStringIO实例吗?
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