[Python-ideas] Prevent importing yourself?

Terry Reedy tjreedy at udel.edu
Wed Feb 3 16:16:48 EST 2016


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 at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
Terry Jan Reedy



More information about the Python-ideas mailing list