datetime.date.today() raises "AttributeError: time"

For an unknown reason, datetime.date.today() began throwing a cryptic "AttributeError: time" exception. It took me a while to figure out that this was caused by an accidental overriding of the built-in 'time' module.
Here's an example interactive session which shows the problem:
[tal ~]$ touch time.py [tal ~]$ python Python 2.5.2 (r252:60911, Jul 17 2008, 10:47:50) [GCC 4.0.1 (Apple Inc. build 5484)] on darwin Type "help", "copyright", "credits" or "license" for more information.
import time time.__file__
'time.py'
import datetime datetime.date.today()
Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: time
Here I used version 2.5.2, but I checked and this also happens on 2.6.
It this desired behavior?
At the very least the exception should be more detailed, perhaps to the point of suggesting the probable cause of the error (i.e. overriding the time module).
- Tal

Tal Einat wrote:
For an unknown reason, datetime.date.today() began throwing a cryptic "AttributeError: time" exception. It took me a while to figure out that this was caused by an accidental overriding of the built-in 'time' module.
Here's an example interactive session which shows the problem:
[tal ~]$ touch time.py [tal ~]$ python Python 2.5.2 (r252:60911, Jul 17 2008, 10:47:50) [GCC 4.0.1 (Apple Inc. build 5484)] on darwin Type "help", "copyright", "credits" or "license" for more information.
import time time.__file__
'time.py'
import datetime datetime.date.today()
Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: time
Here I used version 2.5.2, but I checked and this also happens on 2.6.
It this desired behavior?
At the very least the exception should be more detailed, perhaps to the point of suggesting the probable cause of the error (i.e. overriding the time module).
How is this different from any other case where you import a module with a standard library name conflict, thereby confusing modules loaded later standard library. Should we do the same for any error induced in such a way?
regards Steve

Steve Holden wrote:
Tal Einat wrote:
It this desired behavior?
At the very least the exception should be more detailed, perhaps to the point of suggesting the probable cause of the error (i.e. overriding the time module).
How is this different from any other case where you import a module with a standard library name conflict, thereby confusing modules loaded later standard library. Should we do the same for any error induced in such a way?
The difference is that here the exception is generated directly in the C code so you don't get an intelligible traceback. The C code for datetime imports the time module via the Python C API.
In other words, here a function from a module in the stdlib, datetime, barfs unexpectedly because I happen to have a file name time.py hanging around in some directory. There is no traceback and no intelligible exception message, just "AttributeError: time". I had to dig through datetime's C code to figure out which module was being imported via the Python C API, which turned out to be time.
This is rare enough that I've never had something like this happen to me in seven years of heavy Python programming.
- Tal

On Sun, Nov 16, 2008 at 11:55 AM, Tal Einat taleinat@gmail.com wrote:
Steve Holden wrote:
Tal Einat wrote:
It this desired behavior?
At the very least the exception should be more detailed, perhaps to the point of suggesting the probable cause of the error (i.e. overriding the time module).
How is this different from any other case where you import a module with a standard library name conflict, thereby confusing modules loaded later standard library. Should we do the same for any error induced in such a way?
The difference is that here the exception is generated directly in the C code so you don't get an intelligible traceback. The C code for datetime imports the time module via the Python C API.
In other words, here a function from a module in the stdlib, datetime, barfs unexpectedly because I happen to have a file name time.py hanging around in some directory. There is no traceback and no intelligible exception message, just "AttributeError: time". I had to dig through datetime's C code to figure out which module was being imported via the Python C API, which turned out to be time.
Just like Steve told you, this isn't different from other cases. But, at least you get a message a bit more verbose in most cases, like:
Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'module' object has no attribute 'time'
Then I went to look why this wasn't happening with datetime too, and I found out that PyObject_CallMethod in abstract.c re sets the exception message that would have been set by PyObject_GetAttr by now. Maybe someone can tell me why it is doing that, for now a patch is attached here (I didn't resist to not remove two trailing whitespaces).
This is rare enough that I've never had something like this happen to me in seven years of heavy Python programming.
- Tal
Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/ggpolo%40gmail.com

A funny thing just happened to me. I tried out causing this error, just to see how the error message was somehow different, by creating a time.py in /tmp, and running python from there. Then I removed the time.py, and went on working.
Two days later, my usage of zc.buildout are broken with a "module time has no attribute time". Huh?
Turns out, I created an empty time.py in /tmp, just to see the error message. By buildout will when creating eggs from checked out modules, copy them to a directory under /tmp, and evidently run python from /tmp to create the eggs. So that process finds the time.pyc, created from the empty time.py, which I hadn't deleted, and breaks!
Heh. That was funny. Moral of the story: Don't create python modules with names that clash with build in modules in /tmp, even for testing. Or at least, of you do, remember to remove the pyc. :-P Or, reboot your Linux every night. Or well. I guess this could have been avoided in many ways. ;-)
On Sun, Nov 16, 2008 at 17:43, Guilherme Polo ggpolo@gmail.com wrote:
On Sun, Nov 16, 2008 at 11:55 AM, Tal Einat taleinat@gmail.com wrote:
Steve Holden wrote:
Tal Einat wrote:
It this desired behavior?
At the very least the exception should be more detailed, perhaps to the point of suggesting the probable cause of the error (i.e. overriding the time module).
How is this different from any other case where you import a module with a standard library name conflict, thereby confusing modules loaded later standard library. Should we do the same for any error induced in such a way?
The difference is that here the exception is generated directly in the C code so you don't get an intelligible traceback. The C code for datetime imports the time module via the Python C API.
In other words, here a function from a module in the stdlib, datetime, barfs unexpectedly because I happen to have a file name time.py hanging around in some directory. There is no traceback and no intelligible exception message, just "AttributeError: time". I had to dig through datetime's C code to figure out which module was being imported via the Python C API, which turned out to be time.
Just like Steve told you, this isn't different from other cases. But, at least you get a message a bit more verbose in most cases, like:
Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'module' object has no attribute 'time'
Then I went to look why this wasn't happening with datetime too, and I found out that PyObject_CallMethod in abstract.c re sets the exception message that would have been set by PyObject_GetAttr by now. Maybe someone can tell me why it is doing that, for now a patch is attached here (I didn't resist to not remove two trailing whitespaces).
This is rare enough that I've never had something like this happen to me in seven years of heavy Python programming.
- Tal
Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/ggpolo%40gmail.com
-- -- Guilherme H. Polo Goncalves
Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/regebro%40gmail.com

On Dec 10, 2008, at 5:55 AM, Lennart Regebro wrote:
Turns out, I created an empty time.py in /tmp, just to see the error message. By buildout will when creating eggs from checked out modules, copy them to a directory under /tmp, and evidently run python from /tmp to create the eggs. So that process finds the time.pyc, created from the empty time.py, which I hadn't deleted, and breaks!
Sounds like a security hole in zc.buildout. Imagine someone *else* made a time.py in /tmp...
James

On Wed, Dec 10, 2008 at 18:49, James Y Knight foom@fuhm.net wrote:
On Dec 10, 2008, at 5:55 AM, Lennart Regebro wrote:
Turns out, I created an empty time.py in /tmp, just to see the error message. By buildout will when creating eggs from checked out modules, copy them to a directory under /tmp, and evidently run python from /tmp to create the eggs. So that process finds the time.pyc, created from the empty time.py, which I hadn't deleted, and breaks!
Sounds like a security hole in zc.buildout. Imagine someone *else* made a time.py in /tmp...
Yup. Adam Olsen also reminded me of this, and I have filed a bug report.

On Wed, Dec 10, 2008 at 6:49 PM, James Y Knight foom@fuhm.net wrote:
On Dec 10, 2008, at 5:55 AM, Lennart Regebro wrote:
Turns out, I created an empty time.py in /tmp, just to see the error message. By buildout will when creating eggs from checked out modules, copy them to a directory under /tmp, and evidently run python from /tmp to create the eggs. So that process finds the time.pyc, created from the empty time.py, which I hadn't deleted, and breaks!
Sounds like a security hole in zc.buildout. Imagine someone *else* made a time.py in /tmp...
the current working directory is also added to sys.path if PYTHONPATH contains an empty element. might be the case here...
- Ralf
participants (6)
-
Guilherme Polo
-
James Y Knight
-
Lennart Regebro
-
Ralf Schmitt
-
Steve Holden
-
Tal Einat