2013-05-31 2 views
1

Рассмотрите производительность, я пишу функцию в цитоне, чтобы передать строку в dict. линия кажется,В чем проблема преобразования кода кода cython (pyx) в dict?

" a: 1 b:2 sdf:3.0 \t ggg:vv"

Результат ДИКТ должен быть

{'a': '1', 'b': '2', 'sdf': '3.0', 'ggg': 'vv'} 

Код Cython является:

from libc.string cimport strsep, strlen, strdup 
def line2dict(line): 
    cdef char* line_str = strdup(line) 
    cdef char* item_delim = " \t" 
    cdef char* kv_delim = ":" 

    cdef char* kv_str 
    cdef char* k_str 

    ret = {} 
    while 1: 
     kv_str = strsep(&line_str, item_delim) 
     if kv_str == NULL: 
      break 
     if strlen(kv_str) == 0: 
      continue 
     k_str = strsep(&kv_str, kv_delim) 
     ret[k_str] = kv_str 

    return ret 

Приведенный выше код может быть скомпилирован в .so, импортируется и вызывается в обычный код python, но это может вызвать «Segm в последующих кодах.

Я новичок в цитоне. Может ли кто-нибудь рассказать мне, что не так с этим кодом?

Спасибо!

+1

Я думаю, что вы не должны создавать словарь python с указателями C в качестве ключей и значений. Вероятно, вам нужно преобразовать эти char * в объекты python. См. Эту ссылку: http://docs.cython.org/src/tutorial/strings.html – jcrudy

ответ

1

Ошибка сегментации, скорее всего, возвращает NULL значение из второго экземпляра strsep. Это произойдет, если у вас есть строка с завершающим пробелом и разделителем ':'. Поскольку вы затем передаете NULL в качестве ключа в словарь, это вызовет ошибку сегментации.

Перед хранением в вашем словаре следует проверить значение NULLk_str.

Существует вторая проблема. Вы никогда не освобождаете память, используемую для дублирования вашей строки, с strdup, которая будет тратить лишнюю память. Я бы назвал free, который может быть cimported от libc.stdlib после того, как вы закончили токенизацию своей строки, но перед возвратом.

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