Cython: “erro fatal: numpy / arrayobject.h: esse arquivo ou diretório não existe”


133

Estou tentando acelerar a resposta aqui usando Cython. Eu tento compilar o código (depois de fazer o cygwinccompiler.pyhack explicado aqui ), mas recebo um fatal error: numpy/arrayobject.h: No such file or directory...compilation terminatederro. Alguém pode me dizer se é um problema com o meu código ou alguma sutileza esotérica com o Cython?

Abaixo está o meu código.

import numpy as np
import scipy as sp
cimport numpy as np
cimport cython

cdef inline np.ndarray[np.int, ndim=1] fbincount(np.ndarray[np.int_t, ndim=1] x):
    cdef int m = np.amax(x)+1
    cdef int n = x.size
    cdef unsigned int i
    cdef np.ndarray[np.int_t, ndim=1] c = np.zeros(m, dtype=np.int)

    for i in xrange(n):
        c[<unsigned int>x[i]] += 1

    return c

cdef packed struct Point:
    np.float64_t f0, f1

@cython.boundscheck(False)
def sparsemaker(np.ndarray[np.float_t, ndim=2] X not None,
                np.ndarray[np.float_t, ndim=2] Y not None,
                np.ndarray[np.float_t, ndim=2] Z not None):

    cdef np.ndarray[np.float64_t, ndim=1] counts, factor
    cdef np.ndarray[np.int_t, ndim=1] row, col, repeats
    cdef np.ndarray[Point] indices

    cdef int x_, y_

    _, row = np.unique(X, return_inverse=True); x_ = _.size
    _, col = np.unique(Y, return_inverse=True); y_ = _.size
    indices = np.rec.fromarrays([row,col])
    _, repeats = np.unique(indices, return_inverse=True)
    counts = 1. / fbincount(repeats)
    Z.flat *= counts.take(repeats)

    return sp.sparse.csr_matrix((Z.flat,(row,col)), shape=(x_, y_)).toarray()

você pode adicionar uma marca para qual sistema operacional você está usando?
tacaswell

@tcaswell Windows 7. de 64 bits
Noob Saibot

adicionou a tag windows, espero que ajude esse problema a ser visto por pessoas que sabem usar o windows (diferente de mim).
tacaswell

1
Eu encontrei isso . Parte da terminologia está acima da minha cabeça, mas eu vou dar uma olhada.
Noob Saibot

Respostas:


186

No seu setup.py, o Extensiondeve ter o argumento include_dirs=[numpy.get_include()].

Além disso, você está ausente np.import_array()no seu código.

-

Exemplo setup.py:

from distutils.core import setup, Extension
from Cython.Build import cythonize
import numpy

setup(
    ext_modules=[
        Extension("my_module", ["my_module.c"],
                  include_dirs=[numpy.get_include()]),
    ],
)

# Or, if you use cythonize() to make the ext_modules list,
# include_dirs can be passed to setup()

setup(
    ext_modules=cythonize("my_module.pyx"),
    include_dirs=[numpy.get_include()]
)    

4
Por que eu precisaria np.import_array()? Não é isso para o Numpy C-API ?
Noob Saibot

Eu tentei a sua ideia, mas agora eu recebo este erro louco que é muito longo para postar aqui, mas ele começa comwarning: untitled.pyx:8:49: Buffer unpacking not optimized away.
Noob Saibot

Ah, verdade, você provavelmente não precisa np.import_array(). Porém, eu raramente escrevo extensões Cython que usam sonolentas sem ela, então eu as uso como uma questão de hábito. Quanto ao seu outro problema, o que você citou é apenas um aviso, não um erro. Se você tiver outros erros que precisam ser corrigidos, faça uma nova postagem.
Robert Kern

1
include_dirs=[numpy.get_include()]é um bom truque, obrigado!
Daniel Farrell

14
include_dirspassado para setup()fica ignorado nas últimas distutils, tem que ser passado para cada Extension, pelo menos no mac
dashesy

45

Para um projeto de um arquivo como o seu, outra alternativa é usar pyximport. Você não precisa criar um setup.py... nem precisa abrir uma linha de comando se usar o IPython ... é tudo muito conveniente. No seu caso, tente executar estes comandos no IPython ou em um script Python normal:

import numpy
import pyximport
pyximport.install(setup_args={"script_args":["--compiler=mingw32"],
                              "include_dirs":numpy.get_include()},
                  reload_support=True)

import my_pyx_module

print my_pyx_module.some_function(...)
...

Pode ser necessário editar o compilador, é claro. Isso faz com que a importação e a recarga funcionem da mesma forma para os .pyxarquivos, assim como para os .pyarquivos.

Fonte: http://wiki.cython.org/InstallingOnWindows


Obrigado, @SteveB. Mas você pode elaborar um pouco sobre o que você quer dizer com " Para um projeto de arquivo único como o seu ..."? O módulo acima é uma parte (embora importante) de um aplicativo maior. Como pyximportafeta a velocidade do meu código? E finalmente, a seção aqui: " Desde o Cython 0.11, o módulo pyximport também oferece suporte à compilação experimental para módulos Python normais ..." implica que ele ainda tem algumas falhas para resolver. Você pode explicar isso também?
Noob Saibot

1
Re "suporte de compilação experimental para módulos normais do Python" - com o código sugerido acima, os .pymódulos são compilados normalmente (não com o cython) enquanto os .pyxmódulos são compilados com o cython. Se você pyimport = Trueentrar pyximport.install(), ele usará o cython para tudo, mesmo por exemplo import randomou import os. Eu não sugiro usar esse recurso, simplesmente porque não há motivo convincente para usá-lo e isso pode criar problemas. Provavelmente é usado principalmente por desenvolvedores de cython.
21813 Steve Byrnes

Se pyximportfuncionar, ele criará exatamente o mesmo código C de qualquer outro método. Então tente e veja. Eu estava me referindo ao fato de que quando o processo de compilação é suficientemente complicado, por exemplo, links para bibliotecas de sistema externas, você pode achar que o pyximport falha e você precisa de um setup.pye cythonizepara especificar exatamente como construí-lo. Mas o fato de seu .pyxmódulo ter imports ou cimports não significa que ele não possa ser compilado pyximport; pode muito bem estar totalmente bem.
21813 Steve Byrnes

Eu tenho um post do Cython no qual você pode fornecer informações.
Phillip

14

O erro significa que um arquivo de cabeçalho numpy não está sendo encontrado durante a compilação.

Tente fazer export CFLAGS=-I/usr/lib/python2.7/site-packages/numpy/core/include/e, em seguida, compilar. Este é um problema com alguns pacotes diferentes. Há um erro registrado no ArchLinux para o mesmo problema: https://bugs.archlinux.org/task/22326


Onde adiciono a exportlinha? No meu setup.pyarquivo?
Noob Saibot

Não, é um comando shell. Execute-o no seu shell e comece a compilar.
quer

@NoobSaibot no shell (onde você executa python setup.py), execute o export ..comando primeiro. Ele define as variáveis ​​ambientais do shell, e nada diretamente relacionado ao [pc] ython.
tacaswell

@tcaswell: eu imaginei isso. Estou usando o cmd e recebi este 'export' is not recognized as an internal or external command, operable program or batch file.erro ... simplesmente não posso ganhar com este ...
Noob Saibot 02/02

4
@NoobSaibot você está recebendo respostas LUNIX para o que cheira a um problema janelas ....
tacaswell

1

Resposta simples

Uma maneira mais simples é adicionar o caminho ao seu arquivo distutils.cfg. O nome do caminho do Windows 7 é por padrão C:\Python27\Lib\distutils\. Você apenas afirma o seguinte conteúdo e deve funcionar:

[build_ext]
include_dirs= C:\Python27\Lib\site-packages\numpy\core\include

Arquivo de configuração inteiro

Para dar um exemplo de como o arquivo de configuração pode ser, meu arquivo inteiro diz:

[build]
compiler = mingw32

[build_ext]
include_dirs= C:\Python27\Lib\site-packages\numpy\core\include
compiler = mingw32


1

Se você estiver com preguiça de gravar arquivos de instalação e descobrir o caminho para os diretórios de inclusão, tente cyper . Ele pode compilar seu código Cython e configurar o include_dirsNumpy automaticamente.

Carregue seu código em uma string, execute simplesmente cymodule = cyper.inline(code_string)e sua função estará disponível cymodule.sparsemakerinstantaneamente. Algo assim

code = open(your_pyx_file).read()
cymodule = cyper.inline(code)

cymodule.sparsemaker(...)
# do what you want with your function

Você pode instalar o cyper via pip install cyper.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.