简体   繁体   中英

Pydev source file hyperlinks in Eclipse console

When a python app crashes the console displays hyperlinks to the source code where the exceptions occurred. You just click the link and your source file is opened in the Eclipse editor.

I have my own exception handler and would like to put links to source files in the console when my apps crash.

I have looked for info on this a few times and cannot see how to do it or if it is possible at all.

It seems that it can be done in java by writing to the console in the form ':' - A listener picks this up and converts it to a clickable link. This does not work in Python.

Any ideas?

If you want to put links to be clickable in PyDev, you have to do it in the same way that's presented in Python.

Ie: You can see from https://github.com/fabioz/Pydev/blob/master/plugins/org.python.pydev.debug/src/org/python/pydev/debug/ui/PythonConsoleLineTracker.java that the pattern it matches is:

.*(File) \\\\\\"([^\\\\\\"]*)\\\\\\", line (\\\\d*).

(note that \\ is the escape in a string on on java).

import logging, sys, os
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG, format='%(message)s | \'%(name)s:%(lineno)s\'')
log = logging.getLogger(os.path.basename(__file__))

log.debug("hello logging linked to source")

The above is all you need, below is more extended discussion, includes use of a config file for formatting and a wrapper around getLogger.

Two additional regexes were added Nov 19, 2017, so that a logging formatter in a logging config just needs to include '%(filename)s:%(lineno)s' to create a more concise link. Example:

[formatter_customFormatter] format=%(asctime)s | %(name)s | %(levelname)s | %(message)s '%(filename)s:%(lineno)s'

Yet this fails when calling imported code from subdirectories, since filename doesn't include any path info. Using %(filepath)s works, but at the cost of printing the entire absolute path appended to your log output, the same problem encountered with the previous File regex. But %(name)s usually has almost exactly what you want, parent_dir.filename, because common practice is to pass __name__ to the getLogger call. What to do?

logging.getLogger(__name__.replace(".","/") + ".py")

You could also write a wrapper around getLogger with same code as in

def getLogger(name): return logging.getLogger(name.replace(".","/") + ".py")

and then your call for Logger would be normal

logger = myLogger.getLogger(__name__).

One caveat is that __name__ is '__main__' where main is run, so you need to treat differently to get link from file. One easy way is to just pass my_filename_with_main instead of __name__ to getLogger.

or perhaps use a different wrapper for everything as in

def getLogger(name): from os import path name = path.basename(name) return logging.getLogger(name)

and then your call for Logger would be

logger = myLogger.getLogger(__file__).

And then no special treatment in case file run as '__main__'
Here is a format example, name is whatever is passed to getLogger:
format=%(asctime)s | %(levelname)s | %(name)-20s | %(funcName)-10s | %(message)-35s | '%(name)s:%(lineno)s'

The link provided by Fabio, March '17 very helpful, I'll repeat it here, https://github.com/fabioz/Pydev/blob/master/plugins/org.python.pydev.debug/src/org/python/pydev/debug/ui/PythonConsoleLineTracker.java lines 102 - 104 where the regexes can be found.

Note: PyCharm only liked the single quote version (as given above), Eclipse was not so particular, either worked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM