%% cython_pyximport ImportError:构建模块函数失败:[' DistutilsPlatformError:无法找到vcvarsall.bat \ n']

时间:2014-06-09 09:57:46

标签: python-2.7 cython ipython-notebook importerror

在iPython笔记本中我试图使用笔记本功能%%cython_pyximport编写一个cython函数,我稍后可以在笔记本中调用它。

我想使用此命令而不是%%cython,因为它似乎有相当多的开销。例如,当我描述我的代码时,我得到了这个:

168495 function calls in 4.606 seconds

      Ordered by: internal time


   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    3.234    3.234    4.605    4.605 {_cython_magic_0ef63e1ad591c89b73223c7a86d78802.knn_alg}
    11397    0.326    0.000    0.326    0.000 {method 'reduce' of 'numpy.ufunc' objects}
      987    0.152    0.000    0.266    0.000 decomp.py:92(eig)
      987    0.118    0.000    0.138    0.000 function_base.py:3112(delete)

我希望使用%%cython_pyximport会减少调用此函数所花费的时间。如果有更好的方法,请告诉我。

所以回到我的实际问题 - 当我使用%%cython_pyximport时,我收到此错误:

ImportError: Building module function failed: ['DistutilsPlatformError: Unable to find vcvarsall.bat\n']

也许这与我的PATH上没有的东西有关,但我不确定。我该怎么做才能解决这个问题?

我正在使用Windows 7,Python 2.7.6(与Anaconda一起安装),Cython 0.20.1,iPython Notebook 2.1.0

编辑: 所以在按照@IanH的建议后,我现在有了这个错误:

fatal error: numpy/arrayobject.h: No such file or directory

似乎需要包含额外的头文件,以便numpy与pyximport一起使用。在这个页面上https://github.com/cython/cython/wiki/InstallingOnWindows提到了这个错误以及如何解决它,但我对如何应用这个错误感到迷失,以便%% cython_pyximport命令在我的笔记本中起作用。

3 个答案:

答案 0 :(得分:1)

这里有两个不同的问题。 我首先要解决你似乎关心的问题。

使用pyximport而不是cython magic函数根本不应该提高速度。 鉴于您的分析结果,似乎这里的真正问题是您在循环内部调用NumPy函数。 在Cython中,你必须跟踪哪些函数调用是在C中完成的,哪些是在Python中完成的。 Numpy通用函数是Python函数,它们需要调用Python函数的成本。

您希望如何解决这个问题完全取决于您的工作。 如果你可以使用NumPy操作巧妙地将循环向量化,这可能是最好的方法,但并非所有问题都可以通过这种方式轻松解决。 有一些方法可以从Cython中调用LAPACK例程,如this answer中所述。 如果你正在进行更简单的操作(比如沿轴的求和等),你可以编写一个函数,它使用cython memoryviews在你的Cython模块内部传递切片。 在blog post中有关于正确方法的讨论。 在Cython中进行这些操作通常会有点困难,但它仍然是一个非常平易近人的问题。

现在,尽管我并不相信pyximport会实际按照您的意愿行事,但我仍然会告诉您如何让它发挥作用。 当distutils尝试使用Visual Studio编译器时,即使您没有为其设置所有内容,也会发生错误。 Anaconda默认使用MinGW进行Cython扩展,但由于某些原因,它没有设置为使用MinGW和pyximport。 虽然这很容易解决。 在您的Python安装目录中(可能是C:\Anaconda或这些行中的某些内容),应该有一个文件Anaconda\Lib\distutils\distutils.cfg。 (如果它不存在则创建它。) 修改它以使其内容包含以下两个选项:

[build]
compiler=mingw32

[build_ext]
compiler = mingw32 

如果我没记错的话,第一个已经包含在Anaconda中了。 在撰写本文时,第二个不是。 你需要它来使pyximport工作。

答案 1 :(得分:0)

由于我安装了VS2015,不得不添加新的环境变量

SET VS90COMNTOOLS=%VS140COMNTOOLS%

来源https://stackoverflow.com/a/10558328/625189

答案 2 :(得分:0)

我遇到了同样的问题,所以我的解决方案是使用:

[构建] 编译器的mingw32 =

[build_ext] compiler = mingw32

在IanH的回答中,我选择直接调用gcc和cython。 我想我实际上只是绕过所有可能的错误

  1. 首先,您需要使用以下命令编译cython:

    cython_commands = ['cython', '-a', '-l', '-p', '-o', c_file_name, file_path]
    cython_feedback = subprocess.call(cython_commands)
    
  2. 然后你需要获取.c文件并通过告诉编译器在哪里查找python库来编译它。

    gcc_commands = ['gcc', '-shared', '-Wall', '-O3', '-I', py_include_dir, '-L', py_libs_dir, '-o', output_name,
                   c_file_name, '-l', a_lib]
    gcc_error = subprocess.call(gcc_commands)
    
  3.   

    py_include_dir:python安装目录的路径,标记为“include”

         

    py_libs_dir:python安装目录的路径标记为'libs'

         

    c_file_name:您希望中间人c文件的路径

         

    a_lib:python安装的名称(例如'python34'或'python35'或'python27')