当我使用petsc4py和cython的组合时,我遇到错误: AttributeError:'list'对象没有属性'rfind'
下面的代码是... / petsc4py / demo / wrap-cython / setup.py的一部分,该项目的一个示例有错误:
def configuration(parent_package='',top_path=None):
INCLUDE_DIRS = []
LIBRARY_DIRS = []
LIBRARIES = []
# PETSc
import os
PETSC_DIR = os.environ['PETSC_DIR']
PETSC_ARCH = os.environ.get('PETSC_ARCH', '')
from os.path import join, isdir
if PETSC_ARCH and isdir(join(PETSC_DIR, PETSC_ARCH)):
INCLUDE_DIRS += [join(PETSC_DIR, PETSC_ARCH, 'include'),
join(PETSC_DIR, 'include')]
LIBRARY_DIRS += [join(PETSC_DIR, PETSC_ARCH, 'lib')]
else:
if PETSC_ARCH: pass # XXX should warn ...
INCLUDE_DIRS += [join(PETSC_DIR, 'include')]
LIBRARY_DIRS += [join(PETSC_DIR, 'lib')]
LIBRARIES += [#'petscts', 'petscsnes', 'petscksp',
#'petscdm', 'petscmat', 'petscvec',
'petsc']
# PETSc for Python
import petsc4py
INCLUDE_DIRS += [petsc4py.get_include()]
# Configuration
from numpy.distutils.misc_util import Configuration
config = Configuration('', parent_package, top_path)
config.add_extension('_Bratu3D',
sources = ['Bratu3D.pyx',
'Bratu3Dimpl.c'],
depends = ['Bratu3Dimpl.h'],
include_dirs=INCLUDE_DIRS + [os.curdir],
libraries=LIBRARIES,
library_dirs=LIBRARY_DIRS,
runtime_library_dirs=LIBRARY_DIRS)
return config
if __name__ == "__main__":
from numpy.distutils.core import setup
setup(**configuration(top_path='').todict())
错误消息是:
CC=/usr/local/openmpi-1.10.2/bin/mpicc F90=/usr/local/openmpi-1.10.2/bin/mpif90 LDSHARED='/usr/local/openmpi-1.10.2/bin/mpicc -fPIC -Wall -Wwrite-strings -Wno-strict-aliasing -Wno-unknown-pragmas -fvisibility=hidden -g3 -shared' \
python setup.py -q build_ext --inplace
Traceback (most recent call last):
File "setup.py", line 66, in <module>
setup(**configuration(top_path='').todict())
File "/home/zhangji/anaconda3/envs/obenv/lib/python3.5/site-packages/numpy/distutils/core.py", line 169, in setup
return old_setup(**new_attr)
File "/home/zhangji/anaconda3/envs/obenv/lib/python3.5/distutils/core.py", line 148, in setup
dist.run_commands()
File "/home/zhangji/anaconda3/envs/obenv/lib/python3.5/distutils/dist.py", line 955, in run_commands
self.run_command(cmd)
File "/home/zhangji/anaconda3/envs/obenv/lib/python3.5/distutils/dist.py", line 974, in run_command
cmd_obj.run()
File "/home/zhangji/anaconda3/envs/obenv/lib/python3.5/site-packages/numpy/distutils/command/build_ext.py", line 82, in run
self.run_command('build_src')
File "/home/zhangji/anaconda3/envs/obenv/lib/python3.5/distutils/cmd.py", line 313, in run_command
self.distribution.run_command(command)
File "/home/zhangji/anaconda3/envs/obenv/lib/python3.5/distutils/dist.py", line 974, in run_command
cmd_obj.run()
File "/home/zhangji/anaconda3/envs/obenv/lib/python3.5/site-packages/numpy/distutils/command/build_src.py", line 147, in run
self.build_sources()
File "/home/zhangji/anaconda3/envs/obenv/lib/python3.5/site-packages/numpy/distutils/command/build_src.py", line 164, in build_sources
self.build_extension_sources(ext)
File "/home/zhangji/anaconda3/envs/obenv/lib/python3.5/site-packages/numpy/distutils/command/build_src.py", line 329, in build_extension_sources
sources, py_files = self.filter_py_files(sources)
File "/home/zhangji/anaconda3/envs/obenv/lib/python3.5/site-packages/numpy/distutils/command/build_src.py", line 389, in filter_py_files
return self.filter_files(sources, ['.py'])
File "/home/zhangji/anaconda3/envs/obenv/lib/python3.5/site-packages/numpy/distutils/command/build_src.py", line 398, in filter_files
(base, ext) = os.path.splitext(source)
File "/home/zhangji/anaconda3/envs/obenv/lib/python3.5/posixpath.py", line 122, in splitext
return genericpath._splitext(p, sep, None, extsep)
File "/home/zhangji/anaconda3/envs/obenv/lib/python3.5/genericpath.py", line 118, in _splitext
sepIndex = p.rfind(sep)
AttributeError: 'list' object has no attribute 'rfind'
make: *** [Bratu3D.so] Error 1
... / petsc4py / demo / wrap-swig / setup.py中的另一个示例具有几乎相同的代码,但没有任何错误。唯一的例外是:
config.add_extension('_Bratu3D',
sources = ['Bratu3D.i',
'Bratu3D.c'],
depends = ['Bratu3D.h'],
include_dirs=INCLUDE_DIRS + [os.curdir],
libraries=LIBRARIES,
library_dirs=LIBRARY_DIRS,
runtime_library_dirs=LIBRARY_DIRS)
非常感谢。
答案 0 :(得分:1)
项目petsc4py/demo/wrap-cython
事实上,代码适用于对此文件进行一些猴子修补:numpy/distutils/command/build_src.py
该方法在numpy 1.11.0上定义为:
def generate_a_pyrex_source(self, base, ext_name, source, extension):
"""Pyrex is not supported, but some projects monkeypatch this method.
That allows compiling Cython code, see gh-6955.
This method will remain here for compatibility reasons.
"""
return []
您必须使用自己的定义覆盖此方法。这是使用python 3.5.1,petsc4py 2.0.0测试的更新脚本:
<强>总结用Cython / setup.py 强>
#!/usr/bin/env python
# $ python setup.py build_ext --inplace
from numpy.distutils.command import build_src
# a bit of monkeypatching ...
import Cython.Compiler.Main
build_src.Pyrex = Cython
build_src.have_pyrex = True
def have_pyrex():
import sys
try:
import Cython.Compiler.Main
sys.modules['Pyrex'] = Cython
sys.modules['Pyrex.Compiler'] = Cython.Compiler
sys.modules['Pyrex.Compiler.Main'] = Cython.Compiler.Main
return True
except ImportError:
return False
build_src.have_pyrex = have_pyrex
##########################
# BEGIN additionnal code #
##########################
from numpy.distutils.misc_util import appendpath
from numpy.distutils import log
from os.path import join as pjoin, dirname
from distutils.dep_util import newer_group
from distutils.errors import DistutilsError
def generate_a_pyrex_source(self, base, ext_name, source, extension):
''' Monkey patch for numpy build_src.build_src method
Uses Cython instead of Pyrex.
Assumes Cython is present
'''
if self.inplace:
target_dir = dirname(base)
else:
target_dir = appendpath(self.build_src, dirname(base))
target_file = pjoin(target_dir, ext_name + '.c')
depends = [source] + extension.depends
if self.force or newer_group(depends, target_file, 'newer'):
import Cython.Compiler.Main
log.info("cythonc:> %s" % (target_file))
self.mkpath(target_dir)
options = Cython.Compiler.Main.CompilationOptions(
defaults=Cython.Compiler.Main.default_options,
include_path=extension.include_dirs,
output_file=target_file)
cython_result = Cython.Compiler.Main.compile(source, options=options)
if cython_result.num_errors != 0:
raise DistutilsError("%d errors while compiling %r with Cython" % (cython_result.num_errors, source))
return target_file
build_src.build_src.generate_a_pyrex_source = generate_a_pyrex_source
########################
# END additionnal code #
########################
def configuration(parent_package='', top_path=None):
INCLUDE_DIRS = []
LIBRARY_DIRS = []
LIBRARIES = []
# PETSc
import os
PETSC_DIR = os.environ['PETSC_DIR']
PETSC_ARCH = os.environ.get('PETSC_ARCH', '')
from os.path import join, isdir
if PETSC_ARCH and isdir(join(PETSC_DIR, PETSC_ARCH)):
INCLUDE_DIRS += [join(PETSC_DIR, PETSC_ARCH, 'include'),
join(PETSC_DIR, 'include')]
LIBRARY_DIRS += [join(PETSC_DIR, PETSC_ARCH, 'lib')]
else:
if PETSC_ARCH:
pass # XXX should warn ...
INCLUDE_DIRS += [join(PETSC_DIR, 'include')]
LIBRARY_DIRS += [join(PETSC_DIR, 'lib')]
LIBRARIES += [ # 'petscts', 'petscsnes', 'petscksp',
# 'petscdm', 'petscmat', 'petscvec',
'petsc']
# PETSc for Python
import petsc4py
INCLUDE_DIRS += [petsc4py.get_include()]
# Configuration
from numpy.distutils.misc_util import Configuration
config = Configuration('', parent_package, top_path)
config.add_extension('Bratu3D',
sources=['Bratu3D.pyx', 'Bratu3Dimpl.c'],
depends=['Bratu3Dimpl.h'],
include_dirs=INCLUDE_DIRS + [os.curdir],
libraries=LIBRARIES,
library_dirs=LIBRARY_DIRS,
runtime_library_dirs=LIBRARY_DIRS)
return config
if __name__ == "__main__":
from numpy.distutils.core import setup
setup(**configuration(top_path='').todict())
答案 1 :(得分:0)
您需要添加
from Cython.Build import cythonize
config.ext_modules[-1] = cythonize(config.ext_modules[-1])
在config.add_extension(...)
问题是sources
最终包含一个空列表,由generate_a_pyrex_source添加。这是因为它本身并不知道如何处理cython文件,所以你需要在模块上运行cythonize
来告诉它如何(如cython documentation中所示)。 / p>
为自己解决这个问题的方法是使用python调试器。运行python3 -m pdb setup.py -q build_ext --inplace
,输入cont
以使其最初运行。你会得到例外。您可以键入up
以向上移动堆栈。
在第(base, ext) = os.path.splitext(source)
行输入print(source)
,以查看它是否为空列表。
在第sources, py_files = self.filter_py_files(sources)
行输入print(sources)
,查看[[], 'Bratu3Dimpl.c']
。然后只是在第329行之前查看distutils/build_src.py
的情况(调用self.filter_py_files
以查看它可能出错的地方。
答案 2 :(得分:0)
我已经通过电子邮件发送了代码编写者,他说NumPy对于支持已经发展,现在代码被打破了。然后重写了安装文件。我测试过它在我的系统中运行良好。