Issue compiling package with Cython extension using toml file

809 views
Skip to first unread message

Oyibo

unread,
Oct 26, 2023, 6:54:44 AM10/26/23
to cython-users
Hello Cython team,

I'm trying to compile a project with a Cython extension using a pyproject.toml file within a Conda virtual environment. I want to build the package in development mode using "pip install --editable ."
The compilation process seems to run smoothly without any errors or warnings, resulting in the generation of both a .c file and a .so file within the package's source folder. I can see the package listed inside the virtual environment by using "conda list."
However, when I attempt to call a function from this package, I encounter an "AttributeError: module <package name> has no attribute <module name>" error.
The module can be imported. The intellisense of my editor shows all modules and functions but they can not be executed.
Is there something I need to modify in my "pyproject.toml" or my "setup.py" file to resolve this issue?

# =============================================================================
# System
# =============================================================================
System: Linux Mint 21.2 Victoria
Python: 3.10.13
Cython: 3.0.0


# =============================================================================
# package tree BEFORE compilation
# =============================================================================
cythontest
├── pyproject.toml
├── README.md
├── setup.py
└── src
    └── cythontest
        ├── cython_module.pyx
        ├── __init__.py
        └── module1.py


# =============================================================================
# package tree AFTER compilation
# =============================================================================
cythontest
├── pyproject.toml
├── README.md
├── setup.py
└── src
    ├── cythontest
    │   ├── cython_module.c
    │   ├── cython_module.cpython-310-x86_64-linux-gnu.so
    │   ├── cython_module.pyx
    │   ├── __init__.py
    │   └── module1.py
    └── cythontest.egg-info
        ├── dependency_links.txt
        ├── PKG-INFO
        ├── SOURCES.txt
        └── top_level.txt


# =============================================================================
# conda list AFTER compilation
# =============================================================================
[...]
cythontest                0.1.0                    pypi_0    pypi
[...]


# =============================================================================
# Error
# =============================================================================
import cythontest
cythontest.cython_module.primes(10)
# AttributeError: module 'cythontest' has no attribute 'cython_module'


# =============================================================================
# pyproject.toml
# =============================================================================
[build-system]
requires = ["setuptools", "Cython"]
build-backend = "setuptools.build_meta"

[project]
name = "cythontest"
version = "0.1.0"
description = "My Python package with Cython extension"
authors = [
  {name = "My Name", email = "m...@email.com"},
]
license = {text = "MIT License"}
readme = "README.md"
requires-python = ">=3.10.0"


# =============================================================================
# setup.py
# =============================================================================
from setuptools import setup, Extension
from Cython.Build import cythonize
# import numpy

# Modules to be compiled and include_dirs when necessary
extensions = [
    Extension(
        "cythontest.cython_module",
        ["src/cythontest/cython_module.pyx"], #include_dirs=[numpy.get_include()],
    ),
]

# This is the function that is executed
setup(name='cythontest',  # Required
      ext_modules = cythonize(extensions, compiler_directives={"language_level": 3, "profile": False}),
)


# =============================================================================
# cython_module.pyx
# =============================================================================
def primes(int nb_primes):
    cdef int n, i, len_p
    cdef int[1000] p
    if nb_primes > 1000:
        nb_primes = 1000
    len_p = 0  # The current number of elements in p.
    n = 2
    while len_p < nb_primes:
        # Is n prime?
        for i in p[:len_p]:
            if n % i == 0:
                break
        # If no break occurred in the loop, we have a prime.
        else:
            p[len_p] = n
            len_p += 1
        n += 1
    result_as_list = [prime for prime in p[:len_p]]
    return result_as_list

Marcel Martin

unread,
Oct 26, 2023, 5:56:34 PM10/26/23
to cython...@googlegroups.com
On 2023-10-26 12:21, Oyibo wrote:
> import cythontest
> cythontest.cython_module.primes(10)
> # AttributeError: module 'cythontest' has no attribute 'cython_module'

Subpackages are not automatically imported when importing the parent, so
maybe you just need to change the import to:

import cythontest.cython_modules

Alternatively, change cythontest/__init__.py to include the line 'from .
import cython_module'. (This is not Cython-specific.)

Regards,
Marcel

Oyibo

unread,
Oct 27, 2023, 3:11:23 AM10/27/23
to cython-users
Hey Marcel,

I was so excited to set up my first cython package that I forgot to link the modules inside my __init__.py file.
I have spent so many hours today searching for this mistake ;-)
Thank you so much for taking the time!!!
I am so happy.

# =============================================================================
# __init__.py
# =============================================================================
from cythontest import cython_module
from cythontest import module1

# =============================================================================
# Call primes

# =============================================================================
import cythontest
cythontest.cython_module.primes(10)
# Out[2]: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
# Yeah!!!

Marcel Martin

unread,
Oct 27, 2023, 4:59:09 AM10/27/23
to cython...@googlegroups.com
Hi,

you’re welcome; I’m glad I could help!

Marcel
Reply all
Reply to author
Forward
0 new messages