Skip to content

Commit

Permalink
Eager child attributes in excluded modules
Browse files Browse the repository at this point in the history
Summary:
Some modules imported at the application level, could be importing modules whose parent is listed in the eager list. The attributes added to the (eager) parent would then be lazy attributes. This is undesirable for the purposes of having whole packages flagged as eager.

For example, doing `import torch.distributed.fsdp` from a non-eager module, adds `fsdp` as a lazy attribute to `torch.distributed` (even when `torch.*` is in the "eager list"). This produces a problem with a PyTorch subsystem that walks all objects inside all the `torch` namespace. This in turn triggers imports and eventually import cycles. This diff prevents adding lazy attributes pointing to children submodules on modules that are flagged as eager.

This is the traceback for the example: P834477377

Reviewed By: cxxxs

Differential Revision: D49647778

fbshipit-source-id: d475bc18964533f2ca810fa3417874c4b9de9752
  • Loading branch information
Kronuz authored and facebook-github-bot committed Sep 26, 2023
1 parent 728a9c7 commit 8d9614c
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 0 deletions.
12 changes: 12 additions & 0 deletions Lib/test/lazyimports/parent_eager_import.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import self
if not self._lazy_imports:
self.skipTest("Test relevant only when running with lazy imports enabled")

import importlib

importlib.set_lazy_imports(excluding=["test.lazyimports.data.metasyntactic.foo.bar"])

import test.lazyimports.data.metasyntactic.foo.bar as bar
import test.lazyimports.data.metasyntactic.foo.bar.baz

self.assertFalse(importlib.is_lazy_import(bar.__dict__, "baz"))
6 changes: 6 additions & 0 deletions Python/import.c
Original file line number Diff line number Diff line change
Expand Up @@ -1648,6 +1648,7 @@ add_lazy_modules(PyThreadState *tstate, PyObject *builtins, PyObject *name)
}
Py_DECREF(lazy_submodules);
}
PyObject *filter = tstate->interp->eager_imports;
while (1) {
Py_ssize_t dot = PyUnicode_FindChar(name, '.', 0, PyUnicode_GET_LENGTH(name), -1);
if (dot < 0) {
Expand All @@ -1657,6 +1658,11 @@ add_lazy_modules(PyThreadState *tstate, PyObject *builtins, PyObject *name)
if (parent == NULL) {
goto error;
}
if (filter != NULL && PySequence_Contains(filter, parent)) {
ret = 0; /* If the direct parent is eager, load eagerly */
goto end;
}
filter = NULL;
Py_XDECREF(child);
child = PyUnicode_Substring(name, dot + 1, PyUnicode_GET_LENGTH(name));
if (child == NULL) {
Expand Down

0 comments on commit 8d9614c

Please sign in to comment.