Skip to content Skip to sidebar Skip to footer

Possible To Know If A Python Module Has Been Reloaded?

I'm trying to track down the cause of a bug: https://github.com/numba/numba/issues/3027 It seems that (for some users of numba, but not all) import sys import numba @numba.njit de

Solution 1:

Although highly frowned upon, some Python 2 code reloads sys to restore the sys.setdefaultencoding() function. This is almost always the cause of this problem.

So you could detect that sys was reloaded by checking for the setdefaultencoding attribute:

if hasattr(sys, 'setdefaultencoding'):
    # sys was reloaded!

This would only work on Python 2. Or you could augment the sys.flags struct sequence with an extra field:

from collections import namedtuple
import sys, re

_sys_flags_fields = re.findall('(\w+)=\d', repr(sys.flags))
_sys_flags_augmented = namedtuple('flags', _sys_flags_fields + ['sys_not_reloaded'])
sys.flags = _sys_flags_augmented(*sys.flags + (1,))

after which you can test with:

if not getattr(sys.flags, 'sys_not_reloaded', 0):

Augmenting sys.flags is safer than most other sys manipulations, as third-party code might be relying on the documented sys attributes and methods to be untampered with, and it also works on Python 3.

You could prevent sys from being reloaded by wrapping __builtin__.reload / importlib.reload / imp.reload:

try:
    # Python 2
    import __builtin__ as targetmodule
except ImportError:
    # Python 3.4 and up
    try:
        import importlib as targetmodule
        targetmodule.reload   # NameError for older Python 3 releases
    except (ImportError, AttributeError):
        # Python 3.0 - 3.3
        import imp as targetmodule

from functools import wraps

def reload_wrapper(f):
    @wraps(f)
    def wrapper(module):
        if getattr(module, '__name__', None) == 'sys':
            raise ValueError('sys should never be reloaded!')
        return f(module)
    return wrapper

targetmodule.reload = reload_wrapper(targetmodule.reload)

Instead of raising an exception, you could just use the warnings module or some other mechanism to record or make noise about the fact that sys is being reloaded; you probably want to include the caller into such warnings.

Execute the above module as early as possible to ensure that you can catch out the code that is doing this, possibly by inserting it into the sitecustomize module, or by triggering it from a .pth file installed into the site-packages directory. Any line in a .pth file that starts with import is executed as Python code by the site.py module at Python startup, so the following contents in such a file:

import yourpackage.sysreload_neutraliser

would inject an import at Python startup time.


Post a Comment for "Possible To Know If A Python Module Has Been Reloaded?"