Cython C-level interface of package: *.pxd files are not found

依然范特西╮ 提交于 2020-02-04 01:46:38

问题


In a nutshell

I try to compile a cython extension called extension2 that cimports a file extension from a self-created package. When building extension2, I get the error that extension.pxd is not found though this file is exactly at the sepcified path.

Details

I am building two packages involving cython, a package A and a package B that depends on A. A is a subpacke of a namespace package nsp. That is, the folder structure looks as follows:

├── nsp
│   └── A
|       ├── extension.pxd
|       ├── extension.pyx
│       └── __init__.py
└── setup.py

Here, setup.py reads as follows:

from setuptools import setup
from setuptools.extension import Extension

# factory function
def my_build_ext(pars):
    # import delayed:
    from setuptools.command.build_ext import build_ext as _build_ext

    # include_dirs adjusted: 
    class build_ext(_build_ext):
        def finalize_options(self):
            _build_ext.finalize_options(self)
            # Prevent numpy from thinking it is still in its setup process:
            __builtins__.__NUMPY_SETUP__ = False
            import numpy
            self.include_dirs.append(numpy.get_include())

    #object returned:
    return build_ext(pars)

extensions = [Extension(nsp.A.extension, ['nsp/A/extension.cpp'])]

setup(
    cmdclass={'build_ext' : my_build_ext},
    setup_requires=['numpy'],
    install_requires=['numpy'], 
    packages=['nsp.A'],
    ext_modules=extensions
    package_data={
        'nsp/A': ['*.pxd', '*.pyx']
    },
)

The setup file is inspired by add-numpy-get-include-argument-to-setuptools-without-preinstalled-numpy and distributing-cython-modules. The cython files were already successfully transformed to .cpp files with another script.

I install the the package A with

pip install .

in the directory of the setup.py. Everything works as desired, and I can find all files of the package under ...\Anaconda3\Lib\site-packages\nsp\A, including the *.pxd files.

Now I seek to create a *.cpp file for an extension2 in order to package it later in the second package B. The file extension2.pxd reads

from nsp.A.extension cimport mymethod

The script to create the *.cpp file reads

from distutils.core import setup, Extension
from Cython.Build import cythonize
import numpy as np
import sys
print(sys.executable)

NAME = 'extension2'
extensions = [Extension(NAME, [NAME+'.pyx'],
                        include_dirs=[np.get_include()]
                        )
              ]

setup(name=NAME,
      ext_modules = cythonize(extensions, language="c++", 
                              compiler_directives=compiler_directives),
      include_dirs=[np.get_include()]
      ) 

When I run this script with python myscript build_ext --inplace, I get an error indicating the pxd file is missing:

from nsp.A.extension cimport mymethod
^
------------------------------------------------------------

.\extension2.pxd:11:0: 'nsp\A\extension.pxd' not found

However, this file exists exactly there. (sys.executable is the Anaconda3 folder that contains the installed package) How can I resolve the issue?

Additional info

I am using python 3.7 on Windows x64


回答1:


Cython does not support implicit namespace packages as of yet. That is, cython searches only subdirectories that contain a file init.*, whereby * can be anything from py, pyc, pyx, and pxd.

I have created a bugtracker report for this issue, in case you want to follow up on whether the issue has been fixed in a newer version yet (I worked with Cython 0.29.14).

Until then, a workaround is to create an empty file __init__.pxd in the folder nsp. This file should be ignored by python, as it is not a *.py file, and lets cython search the subdirectories for packages. The file structure then reads as follows:

├── nsp
│   ├── __init__.pxd
│   └── A
|       ├── extension.pxd
|       ├── extension.pyx
│       └── __init__.py
└── setup.py

To install the additional file __init__.pxd in the namespace package, change the packages argument of setup(...) to packages=['nsp', 'nsp.A'] and the package_data argument to package_data={'': ['*.pxd', '*.pyx']}.

Edit:

The bug has been known to the cython developers and will be fixed in version 3. See Fix for cimport from PEP420 namespace.



来源:https://stackoverflow.com/questions/59545750/cython-c-level-interface-of-package-pxd-files-are-not-found

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!