This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author vstinner
Recipients shihai1991, vstinner
Date 2020-03-24.11:07:36
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1585048057.83.0.203708285213.issue40050@roundup.psfhosted.org>
In-reply-to
Content
I can reproduce the leak with command:

./python -m test -R 3:3 test_leak

File 1:
---
import unittest
import sys
from importlib import _bootstrap as BOOTSTRAP


def _save_and_remove_module(name, orig_modules):
    """Helper function to save and remove a module from sys.modules

    Raise ImportError if the module can't be imported.
    """
    # try to import the module and raise an error if it can't be imported
    if name not in sys.modules:
        __import__(name)
        del sys.modules[name]
    for modname in list(sys.modules):
        if modname == name or modname.startswith(name + '.'):
            orig_modules[modname] = sys.modules[modname]
            del sys.modules[modname]

def _save_and_block_module(name, orig_modules):
    """Helper function to save and block a module in sys.modules

    Return True if the module was in sys.modules, False otherwise.
    """
    saved = True
    try:
        orig_modules[name] = sys.modules[name]
    except KeyError:
        saved = False
    sys.modules[name] = None
    return saved



def import_fresh_module():
    name = 'importlib3'
    fresh = ('importlib',)
    blocked = ('_frozen_importlib', '_frozen_importlib_external')
    orig_modules = {}
    names_to_remove = []
    _save_and_remove_module(name, orig_modules)
    try:
        for fresh_name in fresh:
            _save_and_remove_module(fresh_name, orig_modules)
        for blocked_name in blocked:
            if not _save_and_block_module(blocked_name, orig_modules):
                names_to_remove.append(blocked_name)

        with BOOTSTRAP._ModuleLockManager(name):
            spec = BOOTSTRAP._find_spec(name, None)
            module = BOOTSTRAP.module_from_spec(spec)
            sys.modules[spec.name] = module
            spec.loader.exec_module(module)
            del sys.modules[spec.name]


    finally:
        for orig_name, module in orig_modules.items():
            sys.modules[orig_name] = module
        for name_to_remove in names_to_remove:
            del sys.modules[name_to_remove]

class Tests(unittest.TestCase):
    def test_import_fresh(self):
        import_fresh_module()
---

File 2: Lib/importlib3.py
---
import _imp
import sys

try:
    import _frozen_importlib as _bootstrap
    case = 1
except ImportError:
    case = 2

if case == 2:
    _bootstrap = type(sys)("_bootstrap")
    _bootstrap._weakref = sys.modules['_weakref']

    class ModuleSpec:
        @staticmethod
        def method():
            pass

    spec = ModuleSpec()
    spec.name = "_weakref"

    module = _imp.create_builtin(spec)
    module.__spec__ = spec

    sys.modules["_weakref"] = module
---
History
Date User Action Args
2020-03-24 11:07:37vstinnersetrecipients: + vstinner, shihai1991
2020-03-24 11:07:37vstinnersetmessageid: <1585048057.83.0.203708285213.issue40050@roundup.psfhosted.org>
2020-03-24 11:07:37vstinnerlinkissue40050 messages
2020-03-24 11:07:37vstinnercreate