带有__init __。pyx的Cython包:可能吗?

时间:2015-02-01 09:07:39

标签: python python-2.7 cython python-import python-c-extension

是否可以使用__init__.pyx创建Python 2.7包(编译为__init__.so)?如果是这样的话?我没有运气好运。

以下是我的尝试:

  • setup.py

    #!/usr/bin/env python
    
    from distutils.core import setup
    from distutils.extension import Extension
    from Cython.Distutils import build_ext
    
    foo = Extension(name='foo.__init__', sources=['foo/__init__.pyx'])
    bar = Extension(name='foo.bar', sources=['foo/bar.pyx'])
    
    setup(name='foo',
          packages = ['foo'],
          cmdclass={'build_ext':build_ext},
          ext_modules = [foo, bar])
    
  • foo/__init__.pyx

    import foo.bar
    
    cpdef hello_world():
        print "hello world"
        foo.bar.blah()
    
  • foo/bar.pyx

    cpdef blah():
        print "blah"
    

以上有以下行为:

$ python -c 'import foo; foo.hello_world()'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: No module named foo

我看到了由Python issue #15576修复的this Hg commit。查看Python Hg存储库的equivalent Git commit中的Git mirror,我看到可以从Python v2.7.5标记(以及所有后续的v2.7.x版本)访问提交。有回归吗?

2 个答案:

答案 0 :(得分:14)

根据this really old mailing list post,如果您还有一个__init__.py文件(__init__.py文件未被使用,但似乎有必要将该目录视为模块,因此要加载__init__.so文件。

如果我添加__init__.py

# an exception just to confirm that the .so file is loaded instead of the .py file
raise ImportError("__init__.py loaded when __init__.so should have been loaded")

那么你的例子适用于Linux Python 2.7.3:

$ python -c 'import foo; foo.hello_world()'
hello world
blah

这有一个错误的角落案件的所有迹象,所以可能不推荐。请注意,在Windows上,这对我来说似乎不起作用

ImportError: DLL load failed: %1 is not a valid Win32 application.

附录(有一点额外背景):

这种行为似乎没有明确记录。在Python 1.5时代的the original description of packages中,他们说:

  

没有__init__.py,目录不会被识别为包

  

提示:搜索顺序由函数imp.get_suffixes()返回的后缀列表确定。通常按以下顺序搜索后缀:&#34; .so&#34;,&#34; module.so&#34;,&#34; .py&#34;,&#34; .pyc&#34; 。目录没有明确出现在此列表中,但在其中的所有条目之前。

观察到的行为肯定与此一致 - __init__.py将目录视为包,但.so文件优先加载到.py文件 - 但它几乎不明确。

从Cython的角度来看,这种行为似乎被用来编译标准库(在这种情况下__init__.py总是存在),或者在给出https://github.com/cython/cython/blob/master/tests/build/package_compilation.srctree的测试用例中(和其他几个例子也是如此)。在这些&#34; srctree&#34;文件看起来要扩展为包含__init__.py(和其他文件)然后编译的各种文件夹。可能只有__init__.so只是从未测试过。

答案 1 :(得分:-3)

尝试使用相对导入。

__init__中的

from . import bar

也可能是from . import foo。 Haven在一段时间内没有使用python 2 cython。