标签: cython

用Python包装C库:C,Cython还是ctypes?

我想从Python应用程序中调用C库.我不想包装整个API,只包含与我的案例相关的函数和数据类型.在我看来,我有三个选择:

  1. 在C中创建一个实际的扩展模块.可能是矫枉过正,我也想避免学习扩展写作的开销.
  2. 使用Cython将C库中的相关部分公开给Python.
  3. 在Python中完成所有工作,使用ctypes与外部库进行通信.

我不确定2)或3)是否是更好的选择.3)的优点是它ctypes是标准库的一部分,结果代码将是纯Python - 尽管我不确定这个优势实际上有多大.

两种选择都有更多优点/缺点吗?你推荐哪种方法?


编辑:感谢您的所有答案,他们为希望做类似事情的人提供了一个很好的资源.当然,这个决定仍然是针对单个案例做出的 - 没有人"这是正确的事情"的答案.对于我自己的情况,我可能会选择ctypes,但我也期待在其他项目中尝试Cython.

由于没有一个真正的答案,接受一个有点武断; 我选择了FogleBird的答案,因为它提供了对ctypes的一些很好的洞察力,它目前也是最高投票的答案.但是,我建议阅读所有答案以获得良好的概述.

再次感谢.

c python ctypes cython

272
推荐指数
11
解决办法
7万
查看次数

我应该如何构建一个包含Cython代码的Python包

我想制作一个包含一些Cython代码的Python包.我已经很好地运行了Cython代码.但是,现在我想知道如何最好地打包它.

对于大多数只想安装软件包的人来说,我想要包含.cCython创建的文件,并安排setup.py编译它以生成模块.然后用户不需要安装Cython来安装软件包.

但对于谁可能要修改包的人,我也想提供用Cython .pyx文件,并以某种方式也允许setup.py使用用Cython编译它们(因此这些用户需要安装用Cython).

我应该如何构建包中的文件以满足这两种情况?

用Cython文档提供了一些指导.但它没有说明如何制作一个单独setup.py处理有/无Cython情况.

python packaging cython

120
推荐指数
5
解决办法
2万
查看次数

Cython:"致命错误:numpy/arrayobject.h:没有这样的文件或目录"

我试图加快答案在这里使用用Cython.我尝试编译代码(在执行此处cygwinccompiler.py解释的hack 之后),但是出错了.任何人都可以告诉我,如果这是我的代码的问题,或Cython的一些深奥的微妙?fatal error: numpy/arrayobject.h: No such file or directory...compilation terminated

以下是我的代码.提前致谢:

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] …
Run Code Online (Sandbox Code Playgroud)

python numpy cython windows-7

119
推荐指数
3
解决办法
7万
查看次数

使用cython和mingw进行编译会产生gcc:错误:无法识别的命令行选项'-mno-cygwin'

我正在尝试使用mingw(64位)在win 7 64位中使用cython编译python扩展.
我正在使用Python 2.6(Active Python 2.6.6)和足够的distutils.cfg文件(将mingw设置为编译器)

执行时

> C:\Python26\programas\Cython>python setup.py build_ext --inplace
Run Code Online (Sandbox Code Playgroud)

我得到一个错误,说gcc没有-mno-cygwin选项:

> C:\Python26\programas\Cython>python setup.py build_ext --inplace
running build_ext
skipping 'hello2.c' Cython extension (up-to-date)
building 'hello2' extension
C:\mingw\bin\gcc.exe -mno-cygwin -mdll -O -Wall -IC:\Python26\include -IC:\Python26\PC -c hello2.c -o build\temp.win-amd64-2.6\Release\hello2.o
gcc: error: unrecognized command line option '-mno-cygwin'
error: command 'gcc' failed with exit status 1
Run Code Online (Sandbox Code Playgroud)

gcc是:

C:\>gcc --version
gcc (GCC) 4.7.0 20110430 (experimental)
Copyright (C) 2011 Free Software Foundation, Inc.
Run Code Online (Sandbox Code Playgroud)

我该怎么办呢?

python distutils mingw cython

114
推荐指数
3
解决办法
6万
查看次数

使用Cython编译主Python程序

我有一个Python2.6程序,可以使用Cython加载编译为.so文件的Python模块.我用Cython将.py模块编译成.so文件,一切正常.

这是我在Cython中使用的setup.py文件:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [
    Extension("ldap", ["ldap.pyx"]),
    Extension("checker", ["checker.pyx"]),
    Extension("finder", ["finder.pyx"]),
    Extension("utils", ["utils.pyx"]),
]

setup(
  name = 'bchecker',
  cmdclass = {'build_ext': build_ext},
  ext_modules = ext_modules
)
Run Code Online (Sandbox Code Playgroud)

所以我知道我可以使用Cython编译Python模块(我猜Cython从我的Python文件创建'C'文件然后编译它们),但是我可以将我的主Python程序编译成可以在Linux平台上执行的程序吗?如果是这样,将欣赏Cython命令行示例.谢谢.

python cython

71
推荐指数
3
解决办法
6万
查看次数

使用LAPACK分发基于Cython的扩展

我正在编写一个包含Cython扩展和使用LAPACK(和BLAS)的Python模块.我打开使用两种clapacklapacke,或某种f2cf2py解决方案,如果必要的.最重要的是,我能够调用lapackblas从用Cython在紧密循环不Python的调用开销例程.

我在这里找到了一个例子.但是,该示例取决于SAGE.我希望我的模块可以在不安装SAGE的情况下进行安装,因为我的用户不太可能想要或不需要SAGE.我的用户很可能安装了numpy,scipy,pandas和scikit的软件包,所以这些都是合理的依赖.使用的接口的最佳组合是什么,以及最小的setup.py文件看起来可以获取必要的信息(来自numpy,scipy等)以进行编译?

编辑: 这是我最终做的.它适用于我的macbook,但我不知道它是多么便携.当然有更好的方法.

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy
from Cython.Build import cythonize
from numpy.distutils.system_info import get_info

# TODO: This cannot be the right way
blas_include = get_info('blas_opt')['extra_compile_args'][1][2:]
includes = [blas_include,numpy.get_include()]

setup(
    cmdclass = {'build_ext': build_ext},
    ext_modules = cythonize([Extension("cylapack", ["cylapack.pyx"],
                                       include_dirs = includes,
                                       libraries=['blas','lapack'])
                   ])
)
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为在我的macbook上,clapack.h头文件与...相同cblas.h.然后我可以在我的pyx文件中执行此操作:

ctypedef np.int32_t …
Run Code Online (Sandbox Code Playgroud)

python numpy cython blas lapack

67
推荐指数
1
解决办法
1996
查看次数

为类型化内存视图分配内存的推荐方法是什么?

有关类型化内存视图Cython文档列出了三种分配给类型化内存视图的方法:

  1. 从原始C指针,
  2. 来自np.ndarray
  3. 来自a cython.view.array.

假设我没有从外部传入我的cython函数的数据,而是想分配内存并将其作为a返回np.ndarray,我选择了哪些选项?还假设该缓冲区的大小不是编译时常量,即我不能在堆栈上分配,但需要malloc选项1.

因此,3个选项可以解释如下:

from libc.stdlib cimport malloc, free
cimport numpy as np
from cython cimport view

np.import_array()

def memview_malloc(int N):
    cdef int * m = <int *>malloc(N * sizeof(int))
    cdef int[::1] b = <int[:N]>m
    free(<void *>m)

def memview_ndarray(int N):
    cdef int[::1] b = np.empty(N, dtype=np.int32)

def memview_cyarray(int N):
    cdef int[::1] b = view.array(shape=(N,), itemsize=sizeof(int), format="i")
Run Code Online (Sandbox Code Playgroud)

让我感到惊讶的是,在所有三种情况下,Cython为内存分配生成了大量代码,特别是调用__Pyx_PyObject_to_MemoryviewSlice_dc_int.这表明(我可能在这里错了,我对Cython内部工作的洞察力非常有限),它首先创建一个Python对象,然后将其"转换"到内存视图中,这似乎是不必要的开销.

一个简单的基准测试并未揭示三种方法之间存在很大差异,其中2是最薄弱的方法.

推荐三种方法中的哪一种?或者有更好的选择吗? …

python memory buffer memory-management cython

65
推荐指数
2
解决办法
1万
查看次数

Docker-compose 不再构建映像(AttributeError:cython_sources)

我正在构建一个 django-react 站点,突然我的 docker-compose 不再构建,尽管需求或图像版本发生了任何更改。

\n

我的requirements.txt 如下所示:

\n
Django>=3.2.4,<4.0\ndjangorestframework>=3.12.4,<3.14.0\ndjangorestframework-simplejwt>=4.8.0,<5.3.0\npsycopg2>=2.8.6,<2.9\ndrf-spectacular>=0.15.1,<0.30\ndjango-allauth>0.5,<1.0\ndj-rest-auth>=3.0,<4.0\n
Run Code Online (Sandbox Code Playgroud)\n

错误输出:

\n
 => [backend internal] load .dockerignore                                                                                                                                                                  0.0s \n => => transferring context: 234B                                                                                                                                                                          0.0s \n => [backend internal] load build definition from Dockerfile                                                                                                                                               0.0s \n => => transferring dockerfile: 933B                                                                                                                                                                       0.0s \n => [backend internal] load metadata for docker.io/library/python:3.9-alpine3.13                                                                                                                           0.5s \n => [backend 1/6] FROM docker.io/library/python:3.9-alpine3.13@sha256:a7cbd1e7784a35a098cedbc8681b790d35ff6030a5e13f043185e2465003a040                                                                     0.0s \n => [backend internal] load build context                                                                                                                                                                  0.0s \n => => transferring context: 2.53kB                                                                                                                                                                        0.0s \n => CACHED [backend 2/6] WORKDIR …
Run Code Online (Sandbox Code Playgroud)

cython pyyaml docker docker-compose

64
推荐指数
4
解决办法
3万
查看次数

扩展python - 到swig,而不是swig或Cython

我发现了我的python代码中的瓶颈,与psycho等一起玩.然后决定为性能编写ac/c ++扩展.

在swig的帮助下,你几乎不需要关心论点等.一切正常.

现在我的问题是:swig创建了一个非常大的py文件,它在调用实际的.pyd或.so代码之前执行了很多'checkings'和'PySwigObject'.

如果你手写这个文件或者让swig这样做,你们中是否有人有任何经验可以获得更多的性能.

c c++ python swig cython

63
推荐指数
7
解决办法
3万
查看次数

如何告诉distutils使用gcc?

我想用Cython包装一个包含C++和OpenMP代码的测试项目,并通过setup.py文件使用distutils构建它.我的文件内容如下所示:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
from Cython.Distutils import build_ext


modules = [Extension("Interface",
                     ["Interface.pyx", "Parallel.cpp"],
                     language = "c++",
                     extra_compile_args=["-fopenmp"],
                     extra_link_args=["-fopenmp"])]

for e in modules:
    e.cython_directives = {"embedsignature" : True}

setup(name="Interface",
     cmdclass={"build_ext": build_ext},
     ext_modules=modules)
Run Code Online (Sandbox Code Playgroud)

-fopenmp标志与gcc一起用于编译和链接OpenMP.但是,如果我只是调用

cls ~/workspace/CythonOpenMP/src $ python3 setup.py build
Run Code Online (Sandbox Code Playgroud)

这个标志无法识别,因为编译器是clang:

running build
running build_ext
skipping 'Interface.cpp' Cython extension (up-to-date)
building 'Interface' extension
cc -Wno-unused-result -fno-common -dynamic -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -I/usr/local/include -I/usr/local/opt/sqlite/include -I/usr/local/Cellar/python3/3.3.0/Frameworks/Python.framework/Versions/3.3/include/python3.3m -c Interface.cpp -o build/temp.macosx-10.8-x86_64-3.3/Interface.o …
Run Code Online (Sandbox Code Playgroud)

python distutils compiler-errors cython

53
推荐指数
3
解决办法
4万
查看次数