سؤال

When turning on Python trace, the filename is provided, along with the module and sourcecode.

Is it possible to show the file path as well as the filename?

I am using:

-m trace -t

In the example below there are two different account_bank_statement.py files in different directories.

17  --- modulename: account_bank_statement, funcname: button_create_invoice
18 account_bank_statement.py(329):         if context is None:
19 account_bank_statement.py(333):         currency =  self.read(cr, uid, ids, ['currency'])[0]['currency']
20  --- modulename: account_bank_statement, funcname: _currency
21 account_bank_statement.py(107):         res = {}
22 account_bank_statement.py(108):         res_currency_obj = self.pool.get('res.currency')

This is a duplicate of this (unanswered) question: Tracing fIle path and line number

An answer that would involve hacking the trace module would work for me.

EDIT

A solution, based on Alfe's answer below. It is intrusive, but is does what I an looking for. I have left the modulename and also added the pathname. I am working with OpenERP and there is often the same modulename defined in multiple locations.

I have not posted this an answer as it is really a refinement of Alfe's solution, so if you like please up vote his answer.

(1) Copy trace.py to your local path (2) Edit as below:

171 def modname(path):
172     """Return a plausible module name for the patch."""
173 
174     base = os.path.basename(path)
175     filename, ext = os.path.splitext(base)
176     return filename

593     def globaltrace_lt(self, frame, why, arg):
594         """Handler for call events.
595 
596         If the code block being entered is to be ignored, returns `None',
597         else returns self.localtrace.
598         """
599         if why == 'call':
600             code = frame.f_code
601             filename = frame.f_globals.get('__file__', None)
602             if filename:
603                 # XXX modname() doesn't work right for packages, so
604                 # the ignore support won't work right for packages
605                 #modulename = fullmodname(filename)
606                 modfile, ext = os.path.splitext(filename)
607                 modulename = fullmodname(modfile)
608                 if modulename is not None:
609                     ignore_it = self.ignore.names(modfile, modulename)
610                     if not ignore_it:
611                         if self.trace:
612                             print (" --- modulename: %s, funcname: %s, filename: %s"
613                                    % (modulename, code.co_name, filename))
614                         return self.localtrace
615             else:
616                 return None

Sample Output

Note there are 2 different module names, contained in different directories, with the same filenames. This modified *trace.py** handles this.

2  --- modulename: register_accounting, funcname: button_create_invoice, filename: /home/sean/unifield/utp729/unifield-wm/register_accounting/account_bank_statement.pyc
3 account_bank_statement.py(329):         if context is None:
4 account_bank_statement.py(333):         currency =  self.read(cr, uid, ids, ['currency'])[0]['currency']
5  --- modulename: account, funcname: _currency, filename: /home/sean/unifield/utp729/unifield-addons/account/account_bank_statement.pyc
6 account_bank_statement.py(107):         res = {}
7 account_bank_statement.py(108):         res_currency_obj = self.pool.get('res.currency')
هل كانت مفيدة؟

المحلول

If patching of trace.py is allowed, this task is easy.

Copy trace.py (from /usr/lib/python2.7/ in my case) to a local directory (e. g. the current one), then patch the function modname(path) in that local copy. That function strips the directories off the module paths, so the package information is lost. The original contains the line

filename, ext = os.path.splitext(base)

which can be changed to

filename, ext = os.path.splitext(path)

in order to not strip the directory.

The output of a call like ./trace.py --trace t.py then looks like this:

 --- modulename: t, funcname: <module>
t.py(3): import mypackage.mymodule
 --- modulename: mypackage/__init__, funcname: <module>
__init__.py(1):   --- modulename: mypackage/mymodule, funcname: <module>
mymodule.py(1): print 42
42
t.py(5): print 5
5
 --- modulename: ./trace, funcname: _unsettrace
trace.py(80):         sys.settrace(None)

I'm tracing a test script called t.py which imports a module mymodule.py which is in a package mypackage (so the filename is ./mypackage/mymodule.py). That module only prints 42, the test script itself prints 5.

Does this solve your issue?

EDIT:

Upon second view, I propose a different patch.

In function globaltrace_lt() the modulename is derived by calling modname(); patch this to call fullmodname():

            modulename = fullmodname(filename)

I think this might be a less intrusive patch.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top