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 に書かれている通りの挙動ですね。