1

我正在尝试使用“from itertools import islice”,以便使用 liblas 模块一次从 *.las 文件中读取多行。(我的目标是逐块阅读)

跟随问题:Python如何一次读取N行

islice() 可用于获取迭代器的下 n 个项目。因此,list(islice(f, n)) 将返回文件 f 的下 n 行的列表。在循环中使用它将为您提供 n 行块中的文件。在文件的末尾,列表可能会更短,最后调用将返回一个空列表。

我使用了以下代码:

from numpy import nonzero
from liblas import file as lasfile
from itertools import islice


chunkSize = 1000000

f = lasfile.File(inFile,None,'r') # open LAS
while True:
    chunk = list(islice(f,chunkSize))
    if not chunk:
        break
    # do other stuff

但我有这个问题:

len(f)
2866390

chunk = list(islice(f, 1000000))
len(chunk)
**1000000**
chunk = list(islice(f, 1000000))
len(chunk)
**1000000**
chunk = list(islice(f, 1000000))
len(chunk)
**866390**
chunk = list(islice(f, 1000000))
len(chunk)
**1000000**

当文件 f 最终到达时,islice 重新开始读取文件。

感谢您的任何建议和帮助。非常感谢

4

2 回答 2

2

编写一个生成器一次生成 n 行似乎很容易:

def n_line_iterator(fobj,n):
    if n < 1:
       raise ValueError("Must supply a positive number of lines to read")

    out = []
    num = 0
    for line in fobj:
       if num == n:
          yield out  #yield 1 chunk
          num = 0
          out = []
       out.append(line)
       num += 1
    yield out  #need to yield the rest of the lines 
于 2012-10-08T14:17:07.737 回答
2

更改file.py属于 liblas 包的源代码。目前__iter__被定义为(src on github

def __iter__(self):
    """Iterator support (read mode only)

      >>> points = []
      >>> for i in f:
      ...   points.append(i)
      ...   print i # doctest: +ELLIPSIS
      <liblas.point.Point object at ...>
    """
    if self.mode == 0:
        self.at_end = False
        p = core.las.LASReader_GetNextPoint(self.handle)
        while p and not self.at_end:
            yield point.Point(handle=p, copy=True)
            p = core.las.LASReader_GetNextPoint(self.handle)
            if not p:
                self.at_end = True
        else:
            self.close()
            self.open()

您会看到,当文件结束时,它会关闭并再次打开,因此迭代会在文件的开头重新开始。

尝试在else一段时间后删除最后一个块,因此该方法的正确代码应该是:

def __iter__(self):
    """Iterator support (read mode only)

      >>> points = []
      >>> for i in f:
      ...   points.append(i)
      ...   print i # doctest: +ELLIPSIS
      <liblas.point.Point object at ...>
    """
    if self.mode == 0:
        self.at_end = False
        p = core.las.LASReader_GetNextPoint(self.handle)
        while p and not self.at_end:
            yield point.Point(handle=p, copy=True)
            p = core.las.LASReader_GetNextPoint(self.handle)
            if not p:
                self.at_end = True
于 2012-10-08T14:31:24.897 回答