Edgewall Software
Modify

Opened 13 years ago

Closed 13 years ago

Last modified 13 years ago

#9962 closed enhancement (fixed)

Traceback for import errors in Trac's loader

Reported by: Sebastian Krysmanski <sebastian@…> Owned by: Christian Boos
Priority: normal Milestone: 0.12.2
Component: general Version: 0.12.1
Severity: normal Keywords:
Cc: Branch:
Release Notes:
API Changes:
Internal Changes:

Description

A Trac plugin I'm currently writing could not be loaded in Trac. Opening the Trac environment with trac-admin resulted in the following (not very good) error message:

> trac-admin testenv/
12:29:53 Trac[env] INFO: -------------------------------- environment startup [Trac 0.12.1] --------------------------------
12:29:53 Trac[loader] ERROR: Skipping "multitrac.cli = multitrac.cli": (can't import "ImportError: cannot import name MultiTracManager")
cannot import name MultiTracManager
Len:  0
Welcome to trac-admin 0.12.1
Interactive Trac administration console.
Copyright (c) 2003-2010 Edgewall Software

Type:  '?' or 'help' for help on commands.
        
Trac [/srv/tracsandbox/testenv]> 

The problem was a nasty cyclic dependency problem. I've created a patch that also logs the traceback of ImportErrors so that they can be more easily "debugged". With this patch the output will look like this:

> trac-admin testenv/
13:04:20 Trac[env] INFO: -------------------------------- environment startup [Trac 0.12.1] --------------------------------
13:04:20 Trac[loader] ERROR: Skipping "multitrac.cli = multitrac.cli": import error 
Traceback (most recent call last):
  File "/usr/local/lib/python2.6/dist-packages/Trac-0.12.1-py2.6.egg/trac/loader.py", line 76, in _load_eggs
    entry.load(require=True)
  File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 1948, in load
    entry = __import__(self.module_name, globals(),globals(), ['__name__'])
  File "/mnt/hgfs/Linux-Share/MultiTrac/plugins/_Incubator/MultiTracAdminPlugin/multitrac/cli.py", line 6, in <module>
    from multitrac.api.manager_apis import MultiTracManager
  File "/mnt/hgfs/Linux-Share/MultiTrac/plugins/_Incubator/MultiTracAdminPlugin/multitrac/api/manager_apis.py", line 4, in <module>
    from multitrac.model.factory import IItemDescriptorFactory
  File "/mnt/hgfs/Linux-Share/MultiTrac/plugins/_Incubator/MultiTracAdminPlugin/multitrac/model/__init__.py", line 5, in <module>
    from repository import *
  File "/mnt/hgfs/Linux-Share/MultiTrac/plugins/_Incubator/MultiTracAdminPlugin/multitrac/model/repository.py", line 5, in <module>
    from multitrac.api.manager_apis import MultiTracManager
ImportError: cannot import name MultiTracManager
Welcome to trac-admin 0.12.1
Interactive Trac administration console.
Copyright (c) 2003-2010 Edgewall Software

Type:  '?' or 'help' for help on commands.
        
Trac [/srv/tracsandbox/testenv]> 

Attachments (1)

import_error.patch (942 bytes ) - added by Sebastian Krysmanski <sebastian@…> 13 years ago.
Patch against Trac 0.12.1

Download all attachments as: .zip

Change History (8)

by Sebastian Krysmanski <sebastian@…>, 13 years ago

Attachment: import_error.patch added

Patch against Trac 0.12.1

comment:1 by Remy Blank, 13 years ago

Milestone: 0.12.2
Owner: set to Remy Blank

Looks good. I know it's an enhancement, but I'm still scheduling it for 0.12.2 because it's a small change and a big help (I have been bitten by the same kind of issue).

comment:2 by Christian Boos, 13 years ago

If we really want backtraces in this situation, the following patch is enough:

  • trac/loader.py

    diff -r d90d27457272 trac/loader.py
    a b def load_eggs(entry_point_name):  
    5454                              item, ue)
    5555            elif isinstance(e, UnknownExtra):
    5656                env.log.error('Skipping "%s": (unknown extra "%s")', item, ue)
    57             elif isinstance(e, ImportError):
    58                 env.log.error('Skipping "%s": (can\'t import "%s")', item, ue)
    5957            else:
    6058                env.log.error('Skipping "%s": %s)', item,
    6159                              exception_to_unicode(e, traceback=True))

(remove the special case for ImportError).

But I'm not sure if this is really a good idea… most of the time, the import errors are self-explaining, from the name of the module that failed to be imported you can figure out the problem.

in reply to:  2 ; comment:3 by Remy Blank, 13 years ago

Replying to cboos:

If we really want backtraces in this situation, the following patch is enough:

Indeed, that's probably even better.

But I'm not sure if this is really a good idea… most of the time, the import errors are self-explaining, from the name of the module that failed to be imported you can figure out the problem.

That's not my experience. The import error can be due to a module imported by the imported module, or any import along the chain of dependencies. Having the traceback allows identifying the real source of the exception.

comment:4 by Sebastian Krysmanski <sebastian@…>, 13 years ago

I wasn't sure about this either. The current (old) implementation creates an error message like this:

(can't import "ImportError: cannot import name MultiTracManager")

I guess the implementation of exception_to_unicode() has been changed sometime in the past to include the exception type (like ImportError). So before this change the error message would have read:

(can't import "cannot import name MultiTracManager")

However, this error message is a little bit … strange, too. From the current code my guess would be that all error messages will look that "strange".

def _log_error(item, e):
	ue = exception_to_unicode(e)
	if isinstance(e, DistributionNotFound):
		env.log.debug('Skipping "%s": ("%s" not found)', item, ue)
	elif isinstance(e, VersionConflict):
		env.log.error('Skipping "%s": (version conflict "%s")',
					  item, ue)
	elif isinstance(e, UnknownExtra):
                env.log.error('Skipping "%s": (unknown extra "%s")', item, ue)
	elif isinstance(e, ImportError):
		env.log.error('Skipping "%s": (can\'t import "%s")', item, ue)
	else:
		env.log.error('Skipping "%s": %s)', item,
                              exception_to_unicode(e, traceback=True))

in reply to:  3 comment:5 by Christian Boos, 13 years ago

Replying to rblank:

Replying to cboos: … from the name of the module that failed to be imported you can figure out the problem.

That's not my experience. The import error can be due to a module imported by the imported module, or any import along the chain of dependencies. Having the traceback allows identifying the real source of the exception.

Well, firing up a python interpreter and redoing that toplevel import will show you the backtrace, but maybe not in some cases… So in the end, please go ahead and do the change if you'd like to ;-)

Last edited 13 years ago by Christian Boos (previous) (diff)

comment:6 by Remy Blank, 13 years ago

Resolution: fixed
Status: newclosed

Patch applied in [10416].

comment:7 by Remy Blank, 13 years ago

Owner: changed from Remy Blank to Christian Boos

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain Christian Boos.
The resolution will be deleted. Next status will be 'reopened'.
to The owner will be changed from Christian Boos to the specified user.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.