On 1/30/2016 1:58 AM, Sjoerd Job Postmus wrote:
Yes, indeed. That's what I was thinking of. I decided to write up a quick hack that added the filename to the exception string.
sjoerdjob$ ../python mod_a.py Traceback (most recent call last): File "mod_a.py", line 4, in <module> print(parse(JSON_DATA)) File "/home/sjoerdjob/dev/cpython/tmp/mod_b.py", line 4, in parse return json.loads(blob) AttributeError: module 'json' (loaded from /home/sjoerdjob/dev/cpython/tmp/json.py) has no attribute 'loads'
Would it help is we added an AttributeError subclass, ModuleAttributeError and raise that instead module_getattro?
Here's the patch, in case anyone is interested.
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 24c5f4c..5cc144a 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -654,17 +654,25 @@ module_repr(PyModuleObject *m) static PyObject* module_getattro(PyModuleObject *m, PyObject *name) { - PyObject *attr, *mod_name; + PyObject *attr, *mod_name, *mod_file; attr = PyObject_GenericGetAttr((PyObject *)m, name); if (attr || !PyErr_ExceptionMatches(PyExc_AttributeError)) return attr; PyErr_Clear(); if (m->md_dict) { _Py_IDENTIFIER(__name__); mod_name = _PyDict_GetItemId(m->md_dict, &PyId___name__); if (mod_name) { - PyErr_Format(PyExc_AttributeError, + _Py_IDENTIFIER(__file__); + mod_file = _PyDict_GetItemId(m->md_dict, &PyId___file__); + if (mod_file && PyUnicode_Check(mod_file)) { + PyErr_Format(PyExc_AttributeError, + "module '%U' (loaded from %U) has no attribute '%U'", mod_name, mod_file, name); + } else { + PyErr_Format(PyExc_AttributeError, "module '%U' has no attribute '%U'", mod_name, name); + } return NULL; } else if (PyErr_Occurred()) {
Unfortunately, I do think this might impose **some** performance issue, but on the other hand, I'd be inclined to think that attribute-errors on module objects are not that likely to begin with, except for typos and issues like these. (And of course the case that you have to support older versions of Python with a slower implementation, but you most often see those checks being done at the module-level, so it would only impact load-time and not running-time.)
The added benefit would be quicker debugging when finally having posted to a forum: "Ah, I see from the message that the path of the module is not likely a standard-library path. Maybe you have a name collision? Check for files or directories named '<module name here>(.py)' in your working directory / project / ... .
(Of course, another option would be to look for other modules of the same name when you get an attribute-error on a module to aid debugging, but I think that's too heavy-weight.)
If that could be done only when the exception escapes to top level and dumps s traceback, that might be reasonable. And it would _definitely_ be helpful. But I don't think it's possible without major changes.
No, indeed, that was also my expectation: helpful, but too big a hassle to be worth it. _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
-- Terry Jan Reedy