AttributeError:'list'对象没有使用petsc4py属性'rfind'

时间:2016-05-12 05:32:38

标签: python cython

当我使用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)

非常感谢。

3 个答案:

答案 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对于支持已经发展,现在代码被打破了。然后重写了安装文件。我测试过它在我的系统中运行良好。