Cython + Windows 8.1 + VS Express 2013
这是另一个关于Windows和Cython的问题……Cython确实能成功编译一些简单的脚本(虽然不是全部),但大多数情况下gcc会报错。我已经在Setup.py
中配置了使用MingW32作为编译器,并在Setup.cfg
中进行了设置。我还安装了MCVS Express,但似乎要使用它作为编译器需要2008版本,而这个版本现在找不到了。我读了很多关于在Windows上无法使用Cython的资料,但还是找不到解决办法。看起来任何包含cdef
的脚本都会编译失败。有人能帮帮我吗?
配置:
- Windows 8.1(当然是64位)
- Python 2.7.6 32位
- Cython 0.20.2,已为32位Windows预编译
- Microsoft Visual Studio Express 2013
测试项目:
- test.py
- setup.py
- setup.cfg
Setup.cfg:
[build]
compiler = mingw32
Setup.py:
from distutils.core import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("test.py")
)
有效的test.py:
def say_hello_to(name):
print("Hello %s!" % name)
失败的test2.py(相应修改Setup.py):
def primes(int kmax):
cdef int n, k, i
cdef int p[1000]
result = []
if kmax > 1000:
kmax = 1000
k = 0
n = 2
while k < kmax:
i = 0
while i < k and n % p[i] != 0:
i = i + 1
if i == k:
p[k] = n
k = k + 1
result.append(n)
n = n + 1
return result
Mingw32错误输出:
PS C:\Users\Raoul\Desktop\cython_trys> python setup.py build_ext --inplace
Compiling test2.py because it changed.
Cythonizing test2.py
Error compiling Cython file:
------------------------------------------------------------
...
def primes(int kmax):
^
------------------------------------------------------------
test2.py:1:15: Expected ')', found 'kmax'
Traceback (most recent call last):
File "setup.py", line 6, in <module>
ext_modules = cythonize("test2.py")
File "C:\Python27\lib\site-packages\Cython\Build\Dependencies.py", line 798, in cythonize
cythonize_one(*args[1:])
File "C:\Python27\lib\site-packages\Cython\Build\Dependencies.py", line 915, in cythonize_one
raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: test2.py
2 个回答
我不太确定这是不是问题的根源,但很可能是:
错误信息是:
cannot open output file C:\Users\Raoul\Desktop\cython_trys\test.pyd: Permission denied
这可能不是因为你没有权限在 cython_trys
里创建新文件,而是因为已经有一个名为 test.pyd
的文件被独占打开了,所以它被锁住了,因此尝试用新文件覆盖它(就像 gcc
正在尝试的那样)会失败。
为什么这个文件会被打开和锁住呢?
如果你在一个交互式的 Python 会话中,或者在一个脚本里执行了 import test
来测试第一个成功的 test.py
,而且你让它一直运行着,那么它就会一直保持 test.pyd
文件打开。最简单的解决办法就是退出那个 Python 会话或者脚本。
或者,你也可以选择创建一个不同名字的新文件,而不是重复使用同一个文件。
Unix 系统的人写的教程通常不会提到这个问题,因为在 Unix 中,文件不会被删除,直到你在文件系统中移除最后一个链接 并且 关闭任何进程中对它的最后一个文件句柄。所以,你可以用 rm
删除一个文件,或者在上面写一个新文件,而任何仍然打开这个文件的人依然可以正常读取和写入它。但在 Windows 中,一旦最后一个文件系统链接消失,这个文件就可以被删除,即使还有其他人持有它的句柄。这显然是个大问题。因此,Windows 到处使用独占访问锁来防止你做这样的事情。
新问题就是你把文件命名成了 test2.py
,而不是 test2.pyx
。
如果你手动操作,Cython 不在乎你把文件叫什么——只要你告诉它要把某段代码当作 Cython 代码来编译,它就会编译。
但是,当你使用 cythonize
函数来创建你的 ext_modules
时,它会根据文件的后缀来猜测文件类型:.py
表示纯 Python 代码,.pyx
表示 Cython 代码。所以,它试图把你的代码当作纯 Python 来编译,当然了,int kmax
在 Python 中不是一个有效的参数。(你在其他测试中遇到的 cdef
错误也是这个原因。)