Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

strange Tracebacks with importlib #59315

Closed
amauryfa opened this issue Jun 20, 2012 · 27 comments
Closed

strange Tracebacks with importlib #59315

amauryfa opened this issue Jun 20, 2012 · 27 comments
Assignees
Labels
release-blocker stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@amauryfa
Copy link
Member

BPO 15110
Nosy @gvanrossum, @brettcannon, @birkenfeld, @amauryfa, @pitrou, @bitdancer, @davidmalcolm, @ericsnowcurrently
Files
  • importlib-frames.patch
  • trim_tb.patch
  • trim_tb2.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/pitrou'
    closed_at = <Date 2012-07-08.19:03:33.673>
    created_at = <Date 2012-06-20.00:11:41.726>
    labels = ['type-bug', 'library', 'release-blocker']
    title = 'strange Tracebacks with importlib'
    updated_at = <Date 2012-07-28.19:53:03.436>
    user = 'https://github.com/amauryfa'

    bugs.python.org fields:

    activity = <Date 2012-07-28.19:53:03.436>
    actor = 'eric.snow'
    assignee = 'pitrou'
    closed = True
    closed_date = <Date 2012-07-08.19:03:33.673>
    closer = 'amaury.forgeotdarc'
    components = ['Library (Lib)']
    creation = <Date 2012-06-20.00:11:41.726>
    creator = 'amaury.forgeotdarc'
    dependencies = []
    files = ['26158', '26308', '26312']
    hgrepos = []
    issue_num = 15110
    keywords = ['patch']
    message_count = 27.0
    messages = ['163233', '163236', '163258', '164010', '164013', '164014', '164015', '164016', '164017', '164018', '164456', '164922', '164923', '164936', '164938', '164939', '164940', '164950', '164961', '164987', '164995', '165012', '165016', '165021', '165032', '165033', '166683']
    nosy_count = 10.0
    nosy_names = ['gvanrossum', 'brett.cannon', 'georg.brandl', 'amaury.forgeotdarc', 'pitrou', 'Arfrever', 'r.david.murray', 'dmalcolm', 'python-dev', 'eric.snow']
    pr_nums = []
    priority = 'release blocker'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue15110'
    versions = ['Python 3.3']

    @amauryfa
    Copy link
    Member Author

    Exceptions during import now display huge tracebacks across importlib._bootstrap, this adds a lot of noise to the error:

    For example, I added some syntax error in distutils/spawn.py, then:

    ~/python/cpython3.x$ ./python -c "from distutils import ccompiler"
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "<frozen importlib._bootstrap>", line 1335, in _handle_fromlist
      File "<frozen importlib._bootstrap>", line 1288, in _find_and_load
      File "<frozen importlib._bootstrap>", line 1255, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 432, in _check_name_wrapper
      File "<frozen importlib._bootstrap>", line 778, in load_module
      File "<frozen importlib._bootstrap>", line 759, in load_module
      File "<frozen importlib._bootstrap>", line 408, in module_for_loader_wrapper
      File "<frozen importlib._bootstrap>", line 647, in _load_module
      File "/home/amauryfa/python/cpython3.x/Lib/distutils/ccompiler.py", line 8, in <module>
        from distutils.spawn import spawn
      File "<frozen importlib._bootstrap>", line 1288, in _find_and_load
      File "<frozen importlib._bootstrap>", line 1255, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 432, in _check_name_wrapper
      File "<frozen importlib._bootstrap>", line 778, in load_module
      File "<frozen importlib._bootstrap>", line 759, in load_module
      File "<frozen importlib._bootstrap>", line 408, in module_for_loader_wrapper
      File "<frozen importlib._bootstrap>", line 635, in _load_module
      File "<frozen importlib._bootstrap>", line 736, in get_code
      File "/home/amauryfa/python/cpython3.x/Lib/distutils/spawn.py", line 14
        does not compile
                       ^
    SyntaxError: invalid syntax

    @amauryfa amauryfa added stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error labels Jun 20, 2012
    @bitdancer
    Copy link
    Member

    importlib is written in python. So you get a python traceback of its execution stack. Yes it is noisy, but I'm not sure that this should be changed, or we'd lose some of the benefit of having importlib written in python. (It also might be really complicated to change...I'm sure Brett will tell us :)

    @birkenfeld
    Copy link
    Member

    I agree that this is not helpful at all in the usual case, i.e. when you *don't* want to debug importlib. The one frame in actual user code (distutils in this case) in the middle is kind of hard to spot, but it is what you want to know. Note that Amaury's example is quite small; in other projects the import chains may go on for 10-20 modules until the ImportError is raised. Good luck finding out where the bad module was imported without cursing.

    This is different from the normal case in user code calling stdlib code, which raises an exception: the user code frames will be near the top, and the stdlib code near the bottom.

    I see several options here, in no particular order of preference:

    1. special-case importlib._bootstrap when printing tracebacks
    2. rewrite the traceback object when raising ImportErrors from importlib
    3. (is there more?)

    @amauryfa
    Copy link
    Member Author

    Here is a patch which removes "<frozen importlib._bootstrap>" frames from tracebacks. Tests are missing, but this gives good result on the few samples I tried.
    "python -v" does not suppress importlib frames.

    @pitrou
    Copy link
    Member

    pitrou commented Jun 25, 2012

    Wouldn't it be better to do it in pure Python in importlib itself?

    @amauryfa
    Copy link
    Member Author

    I tried to do it in importlib, with code like
    raise original_exception.with_traceback(trimmed_traceback)
    but the function containing this very line would always be part of the displayed stack trace.

    @pitrou
    Copy link
    Member

    pitrou commented Jun 25, 2012

    Perhaps at least the trimming should only be done for ImportErrors, then?

    @amauryfa
    Copy link
    Member Author

    No, the example above is a SyntaxError, and I claim the importlib frames should be removed as well.

    @pitrou
    Copy link
    Member

    pitrou commented Jun 25, 2012

    Ah, you're right. But it could become confusing if some error is raised inside of importlib itself (not an ImportError, something else - perhaps a bug).

    So I would suggest the following:

    • trim ImportErrors
    • trim errors raised when executing the code of an imported module (i.e. in _LoaderBasics._load_module())
    • don't trim other errors, since they can be importlib programming errors

    @pitrou
    Copy link
    Member

    pitrou commented Jun 25, 2012

    About this proposal:

    • trim errors raised when executing the code of an imported module (i.e. in _LoaderBasics._load_module())

    The exec() could be isolated in a distinctly-named submethod (e.g. _exec_module()), so that it is easy to detect it in a traceback.

    @birkenfeld
    Copy link
    Member

    Setting to blocker for b2.

    @pitrou
    Copy link
    Member

    pitrou commented Jul 7, 2012

    Here is a patch with tests. Brett, what do you think?

    @pitrou
    Copy link
    Member

    pitrou commented Jul 7, 2012

    By the way, it has to be done in C since tb_next can't be modified from Python code.

    @amauryfa
    Copy link
    Member Author

    amauryfa commented Jul 7, 2012

    Does it work for extension modules?

    @pitrou
    Copy link
    Member

    pitrou commented Jul 7, 2012

    Does it work for extension modules?

    What do you mean?

    @amauryfa
    Copy link
    Member Author

    amauryfa commented Jul 7, 2012

    I added to _ssl.c:

        PyErr_SetString(PyExc_ValueError, "Just a test");
        return NULL;

    Then I tried to import the module:

    ~/python/cpython3.x$ ./python -c "import ssl"
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/home/amauryfa/python/cpython3.x/Lib/ssl.py", line 60, in <module>
        import _ssl             # if we can't import it, let the error propagate
      File "<frozen importlib._bootstrap>", line 1300, in _find_and_load
      File "<frozen importlib._bootstrap>", line 1267, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 432, in _check_name_wrapper
      File "<frozen importlib._bootstrap>", line 347, in set_package_wrapper
      File "<frozen importlib._bootstrap>", line 360, in set_loader_wrapper
      File "<frozen importlib._bootstrap>", line 878, in load_module
    ValueError: Just a test

    @amauryfa
    Copy link
    Member Author

    amauryfa commented Jul 7, 2012

    See also msg164937

    @pitrou
    Copy link
    Member

    pitrou commented Jul 7, 2012

    Ah, right, here is an updated patch which also handles extension modules and frozen ones.

    @brettcannon
    Copy link
    Member

    Looks good to me. Go ahead and commit it.

    @brettcannon brettcannon assigned pitrou and unassigned brettcannon Jul 8, 2012
    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Jul 8, 2012

    New changeset 8c877ad00bc4 by Antoine Pitrou in branch 'default':
    Issue bpo-15110: Fix the tracebacks generated by "import xxx" to not show the importlib stack frames.
    http://hg.python.org/cpython/rev/8c877ad00bc4

    @pitrou
    Copy link
    Member

    pitrou commented Jul 8, 2012

    Thanks, Brett!

    @pitrou pitrou closed this as completed Jul 8, 2012
    @amauryfa
    Copy link
    Member Author

    amauryfa commented Jul 8, 2012

    I really like the "_exec_module" trick, but it should be applied to builtin modules as well. I hacked _sre.c and got:

    ~/python/cpython3.x$ ./python 
    Traceback (most recent call last):
      File "/home/amauryfa/python/cpython3.x/Lib/site.py", line 70, in <module>
        import re
      File "/home/amauryfa/python/cpython3.x/Lib/re.py", line 122, in <module>
        import sre_compile
      File "/home/amauryfa/python/cpython3.x/Lib/sre_compile.py", line 13, in <module>
        import _sre, sys
      File "<frozen importlib._bootstrap>", line 1318, in _find_and_load
      File "<frozen importlib._bootstrap>", line 1285, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 347, in set_package_wrapper
      File "<frozen importlib._bootstrap>", line 360, in set_loader_wrapper
      File "<frozen importlib._bootstrap>", line 443, in _requires_builtin_wrapper
      File "<frozen importlib._bootstrap>", line 493, in load_module
    ValueError: Just a test

    This change correctly hides importlib frames:

    diff -r 9afdd8c25bf2 Lib/importlib/_bootstrap.py
    --- a/Lib/importlib/_bootstrap.py	Sun Jul 08 14:00:06 2012 +0200
    +++ b/Lib/importlib/_bootstrap.py	Sun Jul 08 15:03:27 2012 +0200
    @@ -490,12 +490,15 @@
             """Load a built-in module."""
             is_reload = fullname in sys.modules
             try:
    -            return _imp.init_builtin(fullname)
    +            return self._exec_module(fullname)
             except:
                 if not is_reload and fullname in sys.modules:
                     del sys.modules[fullname]
                 raise
     
    +    def _exec_module(self, fullname):
    +        return _imp.init_builtin(fullname)
    +
         @classmethod
         @_requires_builtin
         def get_code(cls, fullname):

    @brettcannon
    Copy link
    Member

    Re-opening so Antoine can look at Amaury's proposed fix for builtin modules.

    @brettcannon brettcannon reopened this Jul 8, 2012
    @pitrou
    Copy link
    Member

    pitrou commented Jul 8, 2012

    I really like the "_exec_module" trick, but it should be applied to
    builtin modules as well. I hacked _sre.c and got:

    I hadn't thought about this one. Can you apply your patch?

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Jul 8, 2012

    New changeset 37e68da59047 by Amaury Forgeot d'Arc in branch 'default':
    Issue bpo-15110: Also hide importlib frames when importing a builtin module fails.
    http://hg.python.org/cpython/rev/37e68da59047

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Jul 8, 2012

    New changeset 5d43154d68a8 by Amaury Forgeot d'Arc in branch 'default':
    Issue bpo-15110: Copy same docstring as other '_exec_module' methods.
    http://hg.python.org/cpython/rev/5d43154d68a8

    @amauryfa amauryfa closed this as completed Jul 8, 2012
    @ericsnowcurrently
    Copy link
    Member

    bpo-15425 is related. I'm looking into an exception chaining approach that could be applied for this issue too.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    release-blocker stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    6 participants