class MyImporter(object): def find_module(self, fullname, path=None): return self def load_module(self, fullname): raise ImportError("failed") import sys sys.meta_path = [MyImporter()] import datetime
だと「ImportError: failed」になって、
class MyImporter(object): def find_module(self, fullname, path=None): raise ImportError("failed")
だと「ImportError: No module named datetime」になって、
class MyImporter(object): def find_module(self, fullname, path=None): raise Exception("failed")
だと「Exception: failed」になるのは、find_module でImportErrorを上げた時だけ特別扱いされてるってことでしょうか。PEP-302には "If find_module() raises an exception, it will be propagated to the caller, aborting the import." としか書かれてないみたいですけど。
1/9追記
import.c をざっくり追った感じだと、load_packageやimport_submoduleの中で、find_module内で上げられたPyExc_ImportError は捨ててるっぽいですねー。で、return Py_None してることからわかりますが、 load_module から None を返した場合もこれと同等の挙動になります。ただし、これも PEP-302 的には未定義なので、やるべきじゃないんでしょう。
static PyObject *
import_submodule(PyObject *mod, char *subname, char *fullname)
{
..略..
fdp = find_module(fullname, subname, path, buf, MAXPATHLEN+1,
&fp, &loader);
Py_XDECREF(path);
if (fdp == NULL) {
if (!PyErr_ExceptionMatches(PyExc_ImportError))
return NULL;
PyErr_Clear();
Py_INCREF(Py_None);
return Py_None;
}
..略..
m = load_module(fullname, fp, buf, fdp->type, loader);
..略..
return m;
}
なお、path_hooks を実行した際に上げられたImportError はget_path_importer 内で捕捉されて無視されています。これはPEP-302 に書かれている通りの挙動ですね。