import sys
print(sys.stdin)
print(type(sys.stdin))
print(sys.stdin.name)
print(sys.stdin.__dict__)
执行上述命令时,输出如下:
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>
<class '_io.TextIOWrapper'>
<stdin>
{'mode': 'r'}
因此,从上面的代码片段和输出中,我可以看到name
是表示sys.stdin
的_io.TextIOWrapper
实例的属性。在io.TextIOWrapper
的文档中(例如通过$ pydoc io.TextIOWrapper
),它确实将name
列为数据描述符。然而,无论出于什么原因,name
都不会在其__dict__
中显示为一个项目。
当我使用以下命令手动创建io.TextIOWrapper
实例时:
import io
a = io.TextIOWrapper(io.BytesIO())
print(a)
a.name
<_io.TextIOWrapper encoding='UTF-8'>
已打印出来。但是a.name
行抛出了错误:AttributeError: '_io.BytesIO' object has no attribute 'name'
;我期望的AttributeError
,但我没想到会说它是一个_io.BytesIO
对象。
然后,我尝试手动创建一个子类并附加一个name
属性,如下所示:
import io
class NamedTextIOWrapper(io.TextIOWrapper):
def __init__(self, buffer, name=None, **kwargs):
self.name = name
io.TextIOWrapper.__init__(self, buffer, **kwargs)
input = io.BytesIO('abc')
stdin = NamedTextIOWrapper(input, name='<stdin>', encoding='utf-8')
print(stdin.name)
然而,这会遇到:AttributeError: attribute 'name' of '_io.TextIOWrapper' objects is not writable
。
理想情况下,我还希望能够在手动实例化的io.TextIOWrapper
对象中的sys.stdin
实例中维护看似可用的mode
属性。对于sys.stdout
等效项,我假设它们是相同的,只是name
应该设置为'<stdout>'
,mode
应该设置为'w'
。
发布于 2020-03-10 18:30:35
您可以使用在请求name
属性时返回对象属性字典的name
键的方法来覆盖__getattribute__
方法:
class NamedTextIOWrapper(io.TextIOWrapper):
def __init__(self, buffer, name=None, **kwargs):
vars(self)['name'] = name
super().__init__(buffer, **kwargs)
def __getattribute__(self, name):
if name == 'name':
return vars(self)['name']
return super().__getattribute__(name)
因此:
input = io.BytesIO(b'abc')
stdin = NamedTextIOWrapper(input, name='<stdin>', encoding='utf-8')
print(stdin.name)
输出:
<stdin>
https://stackoverflow.com/questions/60622854
复制相似问题