如何在文件输入对象的打开钩子内使用生成器?

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)

请注意,我遵循这个推理(我可能对方法有误 做):

  1. 我尝试创建一个生成器 (tab_filter),它能够 将任何表格转换为 8 个空格。

  2. 然后,我创建了一个可以使用 generator/iterator 和 假设它是一个普通文件 (IterStream).

  3. 我添加了一些外观更改以使其更易于操作 过滤器(@streamfilter 装饰器)。

  4. 我终于创建了一个 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__()