字典赋值崩溃Cython

时间:2018-05-28 09:47:49

标签: python cython

由于word_idxs[token] = row语句,下面的cython代码崩溃了。如果我删除该声明一切正常。以下是我的观察

  1. 当给出不同的文件作为参数
  2. 时,代码可以正常工作
  3. 我尝试打印token,程序在不同时间针对token的不同值崩溃(这不是导致错误的特定单词)
  4. 我尝试分配word_idxs[row]=row,错误仍然存​​在。所以我认为错误与字符串无关
  5. 如果我继续分配相同的密钥,则不会发生错误。例如:word_idxs['constant'] = row
  6. 如果我删除cmatrix[row, col] = fval,那么一切正常
  7. 我是Cython的新手,如果我做了一些根本错误的事情,请指出

     def cload(self, file_path, int dim, long vocab_size):
        print("Loading")
        cdef:
            unsigned int row = 0
            int col = 0
            float [:,:] cmatrix
            cdef dict word_idxs = {}
            char* token
            char* line
    
        matrix = np.zeros([vocab_size, dim], dtype=np.dtype('f'))
        cmatrix = matrix
    
        with open(file_path, 'rb') as f:
            for line in f:
                token = strtok(line, ' \n')
                print(row, token)
    
                word_idxs[token] = row
    
                for col in range(dim) :
                    val = strtok(NULL,' ')
                    fval = atof(val)
                    cmatrix[row, col] = fval
                row += 1
    

1 个答案:

答案 0 :(得分:1)

对我来说最明显的问题是您没有对tokenval的输出进行错误检查。如果NULL到达字符串的末尾,则可以是strtok,而您只是不处理此问题。由于缺乏可验证的例子,很难知道实际问题是什么

然后有几个问题,@ ead在评论中指出:

  1. Python字符串应该是不可变的,但strtok会修改它给出的指针。这不太可能导致您看到的崩溃,但可能会导致Python出现问题。

  2. line很可能是一个无效的指针(因为它所基于的Python对象永远不会被保留)

  3. 我认为这些问题可以用

    这样的方法解决
    cdef char* line_ptr
    for line in f: # line IS NOT TYPED
      line_ba = bytearray(line) # bytearray is mutable - changing it is fine
      line_ptr = line_ba # line_ptr is valid as long as line_ba exists
    

    你的代码和我建议的替代品在Python和C字符串之间有很多转换,这从来都不是非常快(而且难以正确)。看起来像是用Python编写最简单的东西 - 我怀疑你真的从C调用中获益。