2013-03-12 3 views
4

Я хочу скомпилировать функцию python с помощью cython, для чтения двоичного файла, пропускающего некоторые записи (без чтения всего файла, а затем нарезки, поскольку у меня закончилась бы нехватка памяти). Я могу придумать что-то вроде этого:Передача дескриптора файла функции cython

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» также, обработчик файла. Как я могу определить его тип в цитоне, поскольку он не является «стандартным» типом, например. целое число. Спасибо.

+3

Почему важно набирать эту переменную? Поскольку это объект python, вы не получите никакой скорости. – Bakuriu

+0

Если вы хотите присвоить его переменной класса, вы используете тип 'object'. –

+1

Так что написание дескриптора файла не сильно изменится? Я думал, что при наборе всех переменных без исключений улучшена производительность по сравнению с набором некоторых из них. – user2061949

ответ

5

Определение типа fid не поможет, поскольку вызов функций python по-прежнему является дорогостоящим. Попробуйте собрать свой пример с флагом -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 не показывает питона накладные расходы внутри цикла.

Смежные вопросы