__init__.pyx 的 Cython 包:可能吗?
Cython package with __init__.pyx: Possible?
是否可以使用 __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])
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 Hg 存储库的 Python issue #15576 which was fixed by this Hg commit. Looking at the equivalent Git commit in the Git mirror,我看到可以从 Python v2.7.5 标签(以及所有后续的 v2.7.x 版本)。有回归吗?
尝试使用相对导入。
在__init__
中:
from . import bar
也可能是from . import foo
。好久没用 python 2 cython 了。
根据 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.
附录(一些额外的上下文):
似乎没有明确记录此行为。在 the original description of packages 大约 Python 1.5 时代,他们说:
without the __init__.py
, a directory is not recognized as a package
和
Tip: the search order is determined by the list of suffixes returned by the function imp.get_suffixes()
. Usually the suffixes are searched in the following order: ".so", "module.so", ".py", ".pyc". Directories don't explicitly occur in this list, but precede all entries in it.
观察到的行为肯定与此一致 — __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
)创建 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])
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 Hg 存储库的 Python issue #15576 which was fixed by this Hg commit. Looking at the equivalent Git commit in the Git mirror,我看到可以从 Python v2.7.5 标签(以及所有后续的 v2.7.x 版本)。有回归吗?
尝试使用相对导入。
在__init__
中:
from . import bar
也可能是from . import foo
。好久没用 python 2 cython 了。
根据 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.
附录(一些额外的上下文):
似乎没有明确记录此行为。在 the original description of packages 大约 Python 1.5 时代,他们说:
without the
__init__.py
, a directory is not recognized as a package
和
Tip: the search order is determined by the list of suffixes returned by the function
imp.get_suffixes()
. Usually the suffixes are searched in the following order: ".so", "module.so", ".py", ".pyc". Directories don't explicitly occur in this list, but precede all entries in it.
观察到的行为肯定与此一致 — __init__.py
需要将目录视为一个包,但 .so 文件优先于 .py 文件加载 — 但它很难明确。
从 Cython 的角度来看,这种行为似乎被用于编译标准库(在这种情况下 __init__.py
将始终存在),或者在给出的测试用例中 https://github.com/cython/cython/blob/master/tests/build/package_compilation.srctree(还有其他一些例子)。在这些文件中,"srctree" 文件看起来被扩展到包含 __init__.py
(和其他文件)的各种文件夹中,然后进行编译。有可能只有 __init__.so
根本就没有经过测试。