根据这个确实很老的邮件列表帖子,如果您还有一个__init__.py文件,它也可以工作(该__init__.py文件未使用,但对于将目录视为模块,从而__init__.so加载该文件似乎是必需的)。
如果我添加__init__.py:
# an exception just to confirm that the .so file is loaded instead of the .py fileraise ImportError('__init__.py loaded when __init__.so should have been loaded')
那么您的示例可在Linux Python 2.7.3上运行:
$ python -c ’import foo; foo.hello_world()’hello worldblah
这有一个拐弯处的情况,因此不建议使用。请注意,在Windows上,这似乎对我不起作用
ImportError: DLL load Failed: %1 is not a valid Win32 application.
(需要一些额外说明):
似乎没有明确记录此行为。在关于Python1.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经历可能从未被测试过。
解决方法是否可以使用__init__.pyx(编译为__init__.so)创建Python2.7软件包?如果可以,怎么办?我没有运气让它工作。
这是我尝试过的:
setup.py:
#!/usr/bin/env python
from distutils.core import setupfrom distutils.extension import Extensionfrom 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
我看到了此Hgcommit修复的Python问题#15576。在PythonHg存储库的Git镜像中查看等效的Git提交,我发现可以从Pythonv2.7.5标记(以及所有后续v2.7.x版本)访问该提交。有回归吗?