4

一部のレコードをスキップしてバイナリファイルを読み取るために、cython を使用して Python 関数をコンパイルしたいと考えています (メモリが不足するため、ファイル全体を読み取ってからスライスする必要はありません)。私はこのようなものを思い付くことができます:

    def FromFileSkip(fid, count=1, skip=0):            
        if skip>=0:
            data = numpy.zeros(count)
            k = 0
            while k<count:
                try:
                    data[k] = numpy.fromfile(fid, count=1, dtype=dtype)
                    fid.seek(skip, 1)
                    k +=1
                except ValueError:
                    data = data[:k]
                    break
            return data

そして、次のように関数を使用できます。

 f = open(filename)
 data = FromFileSkip(f,...

ただし、関数「FromFileSkip」をcythonでコンパイルするには、関数に含まれるすべてのタイプを定義したいので、ファイルハンドラーも「fid」します。整数などの「標準」型ではないため、cythonでその型を定義するにはどうすればよいですか。ありがとう。

4

1 に答える 1

5

fidPython 関数の呼び出しは依然としてコストがかかるため、 の型を定義しても役に立ちません。「-a」フラグを使用して例をコンパイルして、私が何を意味するかを確認してください。ただし、ファイル処理に低レベルの C 関数を使用して、ループでの Python のオーバーヘッドを回避できます。例として、データはファイルの先頭から始まり、そのタイプはdouble

from libc.stdio cimport *                                                                

cdef extern from "stdio.h":
    FILE *fdopen(int, const char *)

import numpy as np
cimport numpy as np

DTYPE = np.double # or whatever your type is
ctypedef np.double_t DTYPE_t # or whatever your type is

def FromFileSkip(fid, int count=1, int skip=0):
    cdef int k
    cdef FILE* cfile
    cdef np.ndarray[DTYPE_t, ndim=1] data
    cdef DTYPE_t* data_ptr

    cfile = fdopen(fid.fileno(), 'rb') # attach the stream
    data = np.zeros(count).astype(DTYPE)
    data_ptr = <DTYPE_t*>data.data

    # maybe skip some header bytes here
    # ...

    for k in range(count):
        if fread(<void*>(data_ptr + k), sizeof(DTYPE_t), 1, cfile) < 0:
            break
        if fseek(cfile, skip, SEEK_CUR):
            break

    return data

cython -a example.pyxの出力は、ループ内の Python オーバーヘッドを示していないことに注意してください。

于 2013-03-12T22:35:36.510 に答える