While trying to do something similar to what's in the ActiveState recipe titled Constants in Python by Alex Martelli, I ran into the unexpected side-effect (in Python 2.7) that assigning a class instance to an entry in sys.modules
has -- namely that doing so apparently changes the value of __name__
to None
as illustrated in the following code fragment (which breaks part of the code in the recipe):
class _test(object): pass
import sys
print '# __name__: %r' % __name__
# __name__: '__main__'
sys.modules[__name__] = _test()
print '# __name__: %r' % __name__
# __name__: None
if __name__ == '__main__': # never executes...
import test
print "done"
I'd like to understand why this is happening. I don't believe it was that way in Python 2.6 and earlier versions since I have some older code where apparently the if __name__ == '__main__':
conditional worked as expected following the assignment (but no longer does).
FWIW, I also noticed that the name _test
is getting rebound from a class object to None
, too, after the assignment. It seems odd to me that they're being rebound to None
rather than disappearing altogether...
Update:
I'd like to add that any workarounds for achieving the effect of if __name__ == '__main__':
, given what happens would be greatly appreciated. TIA!
Python Modules Explained So when the interpreter runs a module, the __name__ variable will be set as __main__ if the module that is being run is the main program. But if the code is importing the module from another module, then the __name__ variable will be set to that module's name.
The sys. exc_info function returns a 3- tuple with the exception, the exception's parameter, and a traceback object that pinpoints the line of Python that raised the exception. This can be used something like the following not-very-good example. This uses multiple assignment to capture the three elements of the sys.
The sys module in Python provides various functions and variables that are used to manipulate different parts of the Python runtime environment. It allows operating on the interpreter as it provides access to the variables and functions that interact strongly with the interpreter.
This happens because you have overwrite your module when you did sys.modules[__name__] = _test()
so your module was deleted (because the module didn't have any references to it anymore and the reference counter went to zero so it's deleted) but in the mean time the interpreter still have the byte code so it will still work but by returning None
to every variable in your module (this is because python sets all the variables to None
in a module when it's deleted).
class _test(object): pass
import sys
print sys.modules['__main__']
# <module '__main__' from 'test.py'> <<< the test.py is the name of this module
sys.modules[__name__] = _test()
# Which is the same as doing sys.modules['__main__'] = _test() but wait a
# minute isn't sys.modules['__main__'] was referencing to this module so
# Oops i just overwrite this module entry so this module will be deleted
# it's like if i did:
#
# import test
# __main__ = test
# del test
# __main__ = _test()
# test will be deleted because the only reference for it was __main__ in
# that point.
print sys, __name__
# None, None
import sys # i should re import sys again.
print sys.modules['__main__']
# <__main__._test instance at 0x7f031fcb5488> <<< my new module reference.
EDIT:
A fix will be by doing like this:
class _test(object): pass
import sys
ref = sys.modules[__name__] # Create another reference of this module.
sys.modules[__name__] = _test() # Now when it's overwritten it will not be
# deleted because a reference to it still
# exists.
print __name__, _test
# __main__ <class '__main__._test'>
Hope this will explain things.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With