如何在文件输入对象的打开钩子内使用生成器?
How to use a generator inside an openhook in a fileinput object?
我尝试用 8 个空格替换所有制表字符
fileinput
结构,使用 openhook
参数
fileinput
class.
这是我当前的源代码:
from io import TextIOWrapper
class IterStream(TextIOWrapper):
"""
File-like streaming iterator.
"""
def __init__(self, generator):
self.generator = generator
self.iterator = iter(generator)
self.leftover = ''
def __iter__(self):
return self.iterator
def next(self):
return self.iterator.next()
def __next__(self):
return self.iterator.__next__()
def read(self, size):
data = self.leftover
count = len(self.leftover)
try:
while count < size:
chunk = self.__next__()
data += chunk
count += len(chunk)
except StopIteration:
self.leftover = ''
return data
return data[:size]
def readline(self, size):
return self.read(size)
def readlines(self, size):
return self.read(size)
def close(self):
pass
def streamfilter(filter):
def stream(iostream):
return IterStream(filter(iostream))
return stream
@streamfilter
def tab_filter(stream):
for line in stream:
yield line.replace ('\t', ' ' * 8)
def fileinput_hook(filename, mode):
return tab_filter(open(filename, mode))
if __name__ == "__main__":
import fileinput
f = fileinput.input(files='file.txt', openhook=fileinput_hook)
for line in f:
print(f.filename() + ": " + str(f.filelineno()) + ": " + line)
请注意,我遵循这个推理(我可能对方法有误
做):
我尝试创建一个生成器 (tab_filter
),它能够
将任何表格转换为 8 个空格。
然后,我创建了一个可以使用 generator/iterator 和
假设它是一个普通文件 (IterStream
).
我添加了一些外观更改以使其更易于操作
过滤器(@streamfilter
装饰器)。
我终于创建了一个 fileinput_hook()
函数来挂钩
在 fileinput
对象内的文件上。
一切都完成后,我只需要创建一个 fileinput
对象,然后
浏览它。
不幸的是,我收到以下错误:
Traceback (most recent call last):
File "./example.py", line 60, in <module>
for line in f:
File "/usr/lib/python3.5/fileinput.py", line 265, in __next__
line = self.readline()
File "/usr/lib/python3.5/fileinput.py", line 370, in readline
self._buffer = self._file.readlines(self._bufsize)
File "./example.py", line 36, in readlines
return self.read(size)
File "./example.py", line 23, in read
chunk = self.iterator.next()
AttributeError: 'generator' object has no attribute 'next'
那么,我做错了什么,如何实现我想要的呢?我真的吗
远的?有更好的方法吗?
EDIT 在解决了我在 __next__
和 next
之间的混淆之后,我得到以下错误:
Traceback (most recent call last):
File "./example.py", line 63, in <module>
for line in f:
File "/usr/lib/python3.5/fileinput.py", line 265, in __next__
line = self.readline()
File "/usr/lib/python3.5/fileinput.py", line 370, in readline
self._buffer = self._file.readlines(self._bufsize)
File "./example.py", line 39, in readlines
return self.read(size)
File "./example.py", line 26, in read
chunk = self.__next__()
ValueError: I/O operation on uninitialized object
EDIT2
事实上,正如AlokThakur所说的那样......我不知道发生了什么。
如果您使用 python 3.x 那么您应该使用
__next__()
而不是 next()
改变
self.iterator.next()
到
self.iterator.__next__()
我尝试用 8 个空格替换所有制表字符
fileinput
结构,使用 openhook
参数
fileinput
class.
这是我当前的源代码:
from io import TextIOWrapper
class IterStream(TextIOWrapper):
"""
File-like streaming iterator.
"""
def __init__(self, generator):
self.generator = generator
self.iterator = iter(generator)
self.leftover = ''
def __iter__(self):
return self.iterator
def next(self):
return self.iterator.next()
def __next__(self):
return self.iterator.__next__()
def read(self, size):
data = self.leftover
count = len(self.leftover)
try:
while count < size:
chunk = self.__next__()
data += chunk
count += len(chunk)
except StopIteration:
self.leftover = ''
return data
return data[:size]
def readline(self, size):
return self.read(size)
def readlines(self, size):
return self.read(size)
def close(self):
pass
def streamfilter(filter):
def stream(iostream):
return IterStream(filter(iostream))
return stream
@streamfilter
def tab_filter(stream):
for line in stream:
yield line.replace ('\t', ' ' * 8)
def fileinput_hook(filename, mode):
return tab_filter(open(filename, mode))
if __name__ == "__main__":
import fileinput
f = fileinput.input(files='file.txt', openhook=fileinput_hook)
for line in f:
print(f.filename() + ": " + str(f.filelineno()) + ": " + line)
请注意,我遵循这个推理(我可能对方法有误 做):
我尝试创建一个生成器 (
tab_filter
),它能够 将任何表格转换为 8 个空格。然后,我创建了一个可以使用 generator/iterator 和 假设它是一个普通文件 (
IterStream
).我添加了一些外观更改以使其更易于操作 过滤器(
@streamfilter
装饰器)。我终于创建了一个
fileinput_hook()
函数来挂钩 在fileinput
对象内的文件上。
一切都完成后,我只需要创建一个 fileinput
对象,然后
浏览它。
不幸的是,我收到以下错误:
Traceback (most recent call last):
File "./example.py", line 60, in <module>
for line in f:
File "/usr/lib/python3.5/fileinput.py", line 265, in __next__
line = self.readline()
File "/usr/lib/python3.5/fileinput.py", line 370, in readline
self._buffer = self._file.readlines(self._bufsize)
File "./example.py", line 36, in readlines
return self.read(size)
File "./example.py", line 23, in read
chunk = self.iterator.next()
AttributeError: 'generator' object has no attribute 'next'
那么,我做错了什么,如何实现我想要的呢?我真的吗 远的?有更好的方法吗?
EDIT 在解决了我在 __next__
和 next
之间的混淆之后,我得到以下错误:
Traceback (most recent call last):
File "./example.py", line 63, in <module>
for line in f:
File "/usr/lib/python3.5/fileinput.py", line 265, in __next__
line = self.readline()
File "/usr/lib/python3.5/fileinput.py", line 370, in readline
self._buffer = self._file.readlines(self._bufsize)
File "./example.py", line 39, in readlines
return self.read(size)
File "./example.py", line 26, in read
chunk = self.__next__()
ValueError: I/O operation on uninitialized object
EDIT2
事实上,正如AlokThakur所说的那样......我不知道发生了什么。
如果您使用 python 3.x 那么您应该使用
__next__()
而不是 next()
改变
self.iterator.next()
到
self.iterator.__next__()