Ответ 1
В соответствии с это действительно старый список рассылки он работает, если у вас также есть файл __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 они говорят:
без
__init__.py
, каталог не распознается как пакет
и
Совет: порядок поиска определяется списком суффиксов, возвращаемых функцией
imp.get_suffixes()
. Обычно суффиксы выполняются в следующем порядке: ".so", "module.so", ".py", ".pyc". Каталоги явно не встречаются в этом списке, но предшествуют всем элементам в нем.
Наблюдаемое поведение, безусловно, согласуется с этим. __init__.py
необходимо обработать каталог как пакет, но файл .so загружен в предпочтение .py file — но это вряд ли однозначно.
С точки зрения Cython это поведение, по-видимому, используется для компиляции стандартной библиотеки (в этом случае __init__.py
всегда присутствовало) или в тестовых таблицах, данных https://github.com/cython/cython/blob/master/tests/build/package_compilation.srctree (и еще несколько примеров). В них файл srctree выглядит расширенным в различные папки, содержащие __init__.py
(и другие файлы), а затем скомпилированные. Возможно, что только __init__.so
просто не тестировалось.