Possible To Know If A Python Module Has Been Reloaded?
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?"