Python 2.7 error, imported modules "disappear",

I found something very strange. See This Short Code Below.

import os class Logger(object): def __init__(self): self.pid = os.getpid() print "os: %s." %os def __del__(self): print "os: %s." %os def temp_test_path(): return "./[%d].log" %(os.getpid()) logger = Logger() 

This is for illustrative purposes only. It just prints the imported os module, on constroustion and class destruction (ignoring the name of Logger ). However, when I run this, the os module seems to β€œdisappear” to None in the class destructor. Below is the conclusion.

 os: <module 'os' from 'C:\Python27\lib\os.pyc'>. os: None. 

Where it says os: None. - my problem. It should be identical to the first output line. However, look at the python code above in the temp_test_path() function. If I change the name of this function a little, say temp_test_pat() , and leave the rest of the code exactly the same and run it, I will get the expected result (below).

 os: <module 'os' from 'C:\Python27\lib\os.pyc'>. os: <module 'os' from 'C:\Python27\lib\os.pyc'>. 

I can not find any explanation, except that this is a mistake. You can? By the way, I am using the 64-bit version of Windows 7.

+2
python
source share
4 answers

If you rely on shutting down the interpreter to invoke your __del__ , it is possible that the os module was already removed before __del__ . Try explicitly making del logger in your code and sleeping a bit. This should clearly show that the code is functioning as you expect.

I also want to link you with this note in the official documentation about which __del__ cannot be called in the CPython implementation.

+4
source share

I reproduced this. Interesting behavior for sure. One thing that you need to realize is that __del__ not guaranteed even when called upon exiting the interpreter. There is also no specific order for completing objects at the output of the interpreter.

As you exit the interpreter, there is no guarantee that os not deleted first. In this case, it seems that os actually terminates before your Logger object. This probably happens depending on the order in the globals dictionary.

If we just type the globals dictionary keys right before we exit:

 for k in globals().keys(): print k 

you will see:

 temp_test_path __builtins__ __file__ __package__ __name__ Logger os __doc__ logger 

or

 logger __builtins__ __file__ __package__ temp_test_pat __name__ Logger os __doc__ 

Pay attention to where your Logger is located, especially compared to where os is in the list. With temp_test_pat , Logger actually terminates First , so os is still tied to something meaningful. However, it gets finalized last if temp_test_path used.

If you plan to live in real time until the interpreter exits, and you have a cleaning code that you want to run, you can always register a function that will be launched using atexit.register .

+3
source share

Others answered you: undefined order in which global variables (such as os , Logger and Logger ) are removed from the module namespace during shutdown.

However, if you want a workaround, just import os into the local finaliser namespace:

 def __del__(self): import os print "os: %s." %os 

The os module will still be in this place, you just lose your global link to it.

+3
source share

This is to be expected. From the Python Language Reference :

In addition, when del () is called in response to a module to be removed (for example, while a program is running), other global variables reference to the del () method may have already been deleted or in the process of stalling (for example, closing imported equipment down).

in the big red warning field :-)

+2
source share

All Articles