Encontrar la ruta de acceso completa en una traza de Python

Al activar la traza de Python, se proporciona el nombre del archivo, junto con el módulo y el código fuente.

¿Es posible mostrar la ruta del archivo, así como el nombre del archivo?

Estoy usando:

-m trace -t 

En el siguiente ejemplo, hay dos archivos account_bank_statement.py diferentes en directorios diferentes.

 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') 

Este es un duplicado de esta pregunta (sin respuesta): Rastreo de ruta y número de línea

    Una respuesta que implicaría hackear el módulo de rastreo funcionaría para mí.

    EDITAR

    Una solución, basada en la respuesta de Alfe a continuación. Es intrusivo, pero hace lo que estoy buscando. He dejado el nombre de módulo y también he añadido la ruta de acceso. Estoy trabajando con OpenERP y a menudo hay el mismo nombre de módulo definido en varias ubicaciones.

    No he publicado esta respuesta, ya que es realmente un refinamiento de la solución de Alfe, así que si lo desea, por favor vote su respuesta.

    (1) Copie trace.py a su ruta local (2) Edite de la siguiente manera:

     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 

    Salida de muestra

    Tenga en cuenta que hay 2 nombres de módulos diferentes, contenidos en directorios diferentes, con los mismos nombres de archivo. Este * trace.py ** modificado maneja esto.

     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') 

    Si se permite parchear trace.py , esta tarea es fácil.

    Copie trace.py (de trace.py en mi caso) a un directorio local (por ejemplo, el actual), luego aplique la función modname(path) en esa copia local. Esa función elimina los directorios de las rutas del módulo, por lo que la información del paquete se pierde. El original contiene la línea.

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

    que se puede cambiar a

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

    para no despojar el directorio.

    La salida de una llamada como ./trace.py --trace t.py se ve así:

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

    Estoy rastreando un script de prueba llamado t.py que importa un módulo mymodule.py que está en un paquete mypackage (por lo que el nombre del archivo es ./mypackage/mymodule.py ). Ese módulo solo imprime 42, el script de prueba imprime 5.

    ¿Resuelve esto tu problema?

    EDITAR:

    En la segunda vista, propongo un parche diferente.

    En la función globaltrace_lt() el nombre de módulo se deriva llamando a modname() ; parche esto para llamar a fullmodname() :

      modulename = fullmodname(filename) 

    Creo que esto podría ser un parche menos intrusivo.