I am writing some Python scripts to load log files into a database and I included a try…except block like below.
####code### try: # perform some operation - read from file and put in a db table ## some other code#### except Exception as ex: print str(e) #### more code ###
For some reason, whenever an exception happened instead of the error message I wanted to see, I kept seeing a number like 2.718281 in the log. Suddenly, that number looked familiar. Isn’t that the natural log base (e) ? Why or how am I printing that?
I decided to troubleshoot that portion of the code. I pulled the try…except block by itself and made it work as a test script, like below. I simplified it by adding a divide by 0, so it will reach the except block. When I ran this, it behaved perfectly.
try: # perform some operation - I used a simple one - divide by 0 for example. x = 1/0 except Exception as ex: print str(e)
Python caught it and threw the below exception correctly now..
Traceback (most recent call last):
File “test.py”, line 6, in <module>
NameError: name ‘e’ is not defined
Do you see that typo there? I named my Exception variable ex and I was trying to print e. This didn’t throw an exception in my original script. So, that “e” must have had the value printed. How did it get the value? Now, the question seems to Python specific.
I just Googled python and 2.718281. I landed on Python math library. It contains the following constant:
The mathematical constant e = 2.718281…, to available precision.
There you have it. That’s the number, I have been seeing. That kind of explains it, as I was trying to print(str(e)). That makes sense now as to why my simple program threw an exception. I am not importing any library there, so the name “e” is not found.
Then why did my program find the “e” and print math.e? I am not importing math library. After some trial and error, I found the below line being the culprit:
from pylab import *
pylab probably imports the symbols inside math module. But the point here is the different ways of importing libraries in Python.
Gotcha with Python imports
If you are coming from Java, you only have one type of import statement. Using this, you either import all or specific method from a package.
That’s all or none. Once you have done that, you have imported all the names into the global name space. Now, you can access the symbols inside java.math just as BigInteger, BigDecimal etc without qualifying them with package names. This may create name collisions, if you import from different modules that have the same symbol(s).
In Python there are 2 ways of importing:
from math import e
and a variation of that to import all names in the modulmodule
from math import *
The difference between the 2 approaches is that, the first type (import math) actually only imports the “math” namespace. So, to access anything inside math module, you will have to qualify it:
The second approach, particularly, “from <package> import *” is very much like Java import. It imports everything in the math namespace into the global namespace, so you can use symbols from that package without qualifying. That’s how I got my “e” defined suddenly. If there is another module that had e defined, then we would have had a name collision.
So adding pylab import thus into my test script,
from pylab import * try: # perform some operation x = 1/0 except Exception as ex: print str(e)
I have the following output:
If there is another module that had e defined, then we would have had a name collision. Below example shows such collision. In this case, Python took my file variable:
from pylab import * # my file global e = 10.0 try: # perform some operation x = 1/0 except Exception as ex: print str(e), str(math.e)
and the output is,
So, here I am forced to qualify math.e.