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

Ric*_*sen 26 python cython python-import python-c-extension python-2.7

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

这是我尝试过的:

  • 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])
    
    Run Code Online (Sandbox Code Playgroud)
  • foo/__init__.pyx:

    import foo.bar
    
    cpdef hello_world():
        print "hello world"
        foo.bar.blah()
    
    Run Code Online (Sandbox Code Playgroud)
  • foo/bar.pyx:

    cpdef blah():
        print "blah"
    
    Run Code Online (Sandbox Code Playgroud)

以上具有以下行为:

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

我看到Python问题#15576,这是由这个Hg提交修复的.查看Python Hg存储库的Git镜像中的等效Git提交,我看到可以从Python v2.7.5标记(以及所有后续的v2.7.x版本)访问提交.有回归吗?

Dav*_*idW 15

根据这个非常古老的邮件列表帖子,如果你还有一个__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")
Run Code Online (Sandbox Code Playgroud)

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

$ python -c 'import foo; foo.hello_world()'
hello world
blah
Run Code Online (Sandbox Code Playgroud)

这有一个错误的角落案件的所有迹象,所以可能不建议.请注意,在Windows上,这似乎不适合我

ImportError: DLL load failed: %1 is not a valid Win32 application.
Run Code Online (Sandbox Code Playgroud)

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

此行为似乎没有明确记录.在Python 1.5时代的软件包的原始描述中,他们说:

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

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

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

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