Reputation: 6381
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')
Upvotes: 4
Views: 1285
Reputation: 59446
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.
Upvotes: 3