Python Cython编译模块不允许访问定义的函数';模块';不可催缴

Python Cython编译模块不允许访问定义的函数';模块';不可催缴,python,cython,Python,Cython,发现原始错误->来自CyBlack.CyBlack导入CyBlack然后将*numpy\u值作为输入传递。出现了一个新问题,因此为此创建了一个新职位。 我是Cython的新手,尝试将Black(Black Scholes,没有股票红利)从Python转换为Cython。在编译之后,它不允许我实际使用该函数。我相信有经验的人可以很容易地看到这一点并找出原因。我从CyBlack import CyBlack编译并导入函数并调用CyBlack(BlackPnL、Black_S、Black_Texpi

发现原始错误->
来自CyBlack.CyBlack导入CyBlack
然后将
*numpy\u值作为输入传递。出现了一个新问题,因此为此创建了一个新职位。

我是Cython的新手,尝试将Black(Black Scholes,没有股票红利)从Python转换为Cython。在编译之后,它不允许我实际使用该函数。我相信有经验的人可以很容易地看到这一点并找出原因。我从CyBlack import CyBlack编译并导入函数
并调用
CyBlack(BlackPnL、Black_S、Black_Texpiry、Black_strike、Black_volatility、Black_IR、Black_callput)后得到的错误是
TypeError:“module”对象不可调用
:下面是代码:

from numpy cimport ndarray
cimport numpy as np
cimport cython

cdef extern from "math.h":
    double exp(double)
    double sqrt(double)
    double pow(double)
    double log(double)
    double erf(double)

cdef double std_norm_cdf(double x):
    return 0.5*(1+erf(x/sqrt(2.0)))

@cython.boundscheck(False)
cdef CyBlack(ndarray[np.float64_t, ndim=1] BlackPnL, ndarray[np.float64_t, ndim=1] Black_S, ndarray[np.float64_t, ndim=1] Black_Texpiry, ndarray[np.float64_t, ndim=1] Black_strike, ndarray [np.float64_t, ndim=1] Black_volatility, ndarray[np.float64_t, ndim=1] Black_IR, ndarray[np.float64_t, ndim=1] Black_callput):

    cdef Py_ssize_t i
    cdef Py_ssize_t N = BlackPnL.shape[0]
    cdef double d1, d2


    for i in range(N):
        d1 = ((log(Black_S[i] / Black_strike[i]) + Black_Texpiry[i] * Black_volatility[i] **2 / 2)) / (Black_volatility[i] * sqrt(Black_Texpiry[i]))
        d2 = d1 - Black_volatility[i] * sqrt(Black_Texpiry[i])
        BlackPnL[i] = exp(-Black_IR[i] * Black_Texpiry[i]) * (Black_callput[i] * Black_S[i] * std_norm_cdf(Black_callput[i] * d1) - Black_callput[i] * Black_strike[i] * std_norm_cdf(Black_callput[i] * d2)) 

    return BlackPnL
谢谢你的帮助!如果您需要测试一些东西,我可以发布python伪数据-尽管使用任何数据调用它都会暴露错误。。。有些东西向我指出了C代码中没有向Python公开的变量

在此处添加我的
setup.py
,以便其他人可以构建此类型:
python setup.py build\u ext--inplace
为python 3.5 64位窗口使用VS2015构建

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize("CyBlack.pyx"), include_dirs =["C://Program Files (x86)//Microsoft Visual Studio 14.0//VC//include", "C://Program Files (x86)//Windows Kits//10//Include//10.0.1.0240.0//ucrt", "C://Program Files (x86)//Microsoft Visual Studio 14.0//VC//lib//amd64", "C://Anaconda3//Lib//site-packages//numpy//core//include", "C://Program Files (x86)//Microsoft Visual Studio 14.0//VC//lib//amd64"])
而不是

from CyBlack import CyBlack
你为什么不这样做呢

import CyBlack

我设法通过以下方式使(类似的)工作:

C:/dev/tmp/CyBlack/
                   __init__.py
                   setup.py
                   CyBlack.pyx
其中,
CyBlack.pyx
与您的类似,只是
CyBlack
函数为
cpdef
'd<代码>设置.py
包含:

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

extra_compile_args = ['/EHsc', '/openmp', '/favor:INTEL64']

setup(
    ext_modules=cythonize("CyBlack.pyx"),
    include_dirs=['.', numpy.get_include()],
    extra_compile_args=extra_compile_args
)
然后运行:

C:\dev\tmp\CyBlack> python .\setup.py build_ext --compiler=msvc --inplace
将生成
C:/dev/tmp/CyBlack/CyBlack.pyd
,然后我设法从Python运行代码:

>>> from sys import path
>>> path.insert(0, "C:/dev/tmp")
>>> from CyBlack.CyBlack import CyBlack
>>> CyBlack(*[np.array([1.0]) for _ in xrange(7)]) # I'm too lazy to put proper values here...
array([ 0.14087021])

这是用Python2.7完成的,整体设置可能略有不同,但希望这能帮助您获得一个最低限度的工作示例,并追溯如何正确运行。

听起来像是
CyBlack
模块实际上可能嵌入在
CyBlack
包中。你的
CyBlack
函数是cdef'ed而不是cpdef'ed,因此它不能通过任何Python导入来访问。我cpdef'd了它,仍然是同一个问题…你能发布CyBlack导入CyBlack的
结果吗;打印(CyBlack.\uuuuu文件)
?这将输出导致错误的模块的路径。您的目录结构是什么(即您的模块在名为
cyBlack
的目录中)?在名为cyBlack的目录中是。它导入时没有错误,只是不允许您向函数发送参数,这实际上是我第一次尝试的。。。不起作用。我猜在CyBlack模块中可能有一个名为CyBlack的子模块/函数。因此,如果您刚刚导入了CyBlack,那么您可能需要在代码中使用
CyBlack.CyBlack()
,如果它实际上是一个函数的话。感谢您发布运行示例。实际上,我在你碰巧找到的同时找到了埋在地下的模块。现在唯一的问题是函数不允许处理numpy向量(有点违背了拥有内部循环的目的),因为我认为这就是在cython块中声明numpy数组类型的目的。我在传递
nd
向量时也遇到了问题,我怀疑这是因为使用了C
log
sqrt
而不是(矢量化的)numpy;不确定这是否是导致itI的原因。我在上面的代码中添加了[i]索引,该索引应允许每次将1个值传递给
log
sqrt
,但没有帮助。我想我已经把这个问题变成了另一个问题,应该接受你的答案,然后重新发布第2部分。。。