otra - python ejemplo clases
¿Cómo puedo acceder al módulo de ejecución actual o al nombre de la clase en Python? (10)
Creo que lo que quieres usar es el módulo de inspect , para inspeccionar la pila de tiempo de ejecución de python. Echa un vistazo a este tutorial . Creo que proporciona un ejemplo casi exacto de lo que quieres hacer.
Me gustaría poder recuperar dinámicamente el módulo de ejecución actual o el nombre de clase desde un módulo importado. Aquí hay un código:
foo.py:
def f():
print __name__
bar.py:
from foo import f
def b(): f()
Obviamente, esto no funciona, ya que __name__
es el nombre del módulo que contiene la función. Lo que me gustaría tener acceso dentro del módulo foo
es el nombre del módulo de ejecución actual que usa foo
. Entonces, en el caso anterior sería bar
pero si cualquier otro módulo importado foo
me gustaría que foo
tenga acceso dinámico al nombre de ese módulo.
Edición: el módulo de inspect
parece bastante prometedor, pero no es exactamente lo que estaba buscando. Lo que esperaba era algún tipo de variable global o de nivel de entorno a la que pudiera acceder que contuviera el nombre del módulo de ejecución actual. No es que no esté dispuesto a atravesar la pila para encontrar esa información; solo pensé que Python podría haber expuesto ya esos datos.
Edición: Así es como estoy tratando de usar esto. Tengo dos aplicaciones Django diferentes que necesitan registrar errores en el archivo. Digamos que se llaman "AppOne" y "AppTwo". También tengo un lugar en el que me gustaría registrar estos archivos: " /home/hare/app_logs
". En cada aplicación en cualquier punto dado me gustaría poder importar mi módulo de registrador y llamar a la función de registro que escribe la cadena de registro en el archivo. Sin embargo, lo que me gustaría hacer es crear un directorio bajo app_logs
que sea el nombre de la aplicación actual ("AppOne" o "AppTwo") para que los archivos de registro de cada aplicación se incluyan en sus respectivos directorios de registro.
Para hacer esto, pensé que la mejor manera sería que el módulo de registrador tuviera acceso a algún tipo de variable global que denota el nombre de la aplicación actual, ya que es responsable de conocer la ubicación del directorio de registro principal y de crear el registro de la aplicación. Directorio si aún no existe.
Del comentario - no de la pregunta.
Simplemente tengo curiosidad por ver si lo que estoy tratando de hacer es posible.
La respuesta a "es posible" siempre es "sí". Siempre. A menos que su pregunta implique viajes en el tiempo, antigravedad o movimiento perpetuo.
Dado que la respuesta siempre es "sí", su pregunta está mal formada. La verdadera pregunta es "¿cuál es una buena manera de que mi módulo de registro sepa el nombre del cliente?" o algo así.
La respuesta es "Acéptalo como parámetro". No pierdas tiempo inspeccionando o buscando mundos misteriosos u otros trucos.
Simplemente siga el patrón de diseño de logging.getLogger () y use registradores con nombres explícitos. Un idioma común es el siguiente
logger= logging.getLogger( __name__ )
Que maneja casi todos los nombres de registro perfectamente.
El "módulo que se está ejecutando actualmente" es claramente foo, ya que eso es lo que contiene la función que se está ejecutando actualmente. Creo que una mejor descripción de lo que quieres es el módulo del llamador inmediato de foo (que puede ser foo si estás llamando a af () desde una función en foo llamada por una función en la barra. La distancia que desea subir depende de para qué desea esto.
En cualquier caso, suponiendo que desea que la persona que llama de inmediato, puede obtener esto al subir la pila de llamadas. Esto se puede lograr llamando a sys._getframe
, con el número de niveles adecuado para caminar.
def f():
caller = sys._getframe(1) # Obtain calling frame
print "Called from module", caller.f_globals[''__name__'']
[Editar] : En realidad, usar el módulo de inspect como se sugirió anteriormente es probablemente una forma más limpia de obtener el marco de pila. El código equivalente es:
def f():
caller = inspect.currentframe().f_back
print "Called from module", caller.f_globals[''__name__'']
(Se documenta que sys._getframe es para uso interno; el módulo de inspección es una API más confiable)
El uso de __file__
solo le da una ruta relativa para el módulo principal y una ruta absoluta para los módulos importados. Teniendo en cuenta esto, podemos obtener el archivo del módulo constantemente de cualquier manera con un poco de ayuda de nuestras herramientas os.path
.
Para el nombre de archivo solo use __file__.split(os.path.sep)[-1]
.
Para la ruta completa, use os.path.abspath(__file__)
.
Manifestación:
/tmp $ cat f.py
from pprint import pprint
import os
import sys
pprint({
''sys.modules[__name__]'': sys.modules[__name__],
''__file__'': __file__,
''__file__.split(os.path.sep)[-1]'': __file__.split(os.path.sep)[-1],
''os.path.abspath(__file__)'': os.path.abspath(__file__),
})
/tmp $ cat i.py
import f
Resultados:
## on *Nix ##
/tmp $ python3 f.py
{''sys.modules[__name__]'': <module ''__main__'' from ''f.py''>,
''__file__'': ''f.py'',
''__file__.split(os.path.sep)[-1]'': ''f.py'',
''os.path.abspath(__file__)'': ''/tmp/f.py''}
/tmp $ python3 i.py
{''sys.modules[__name__]'': <module ''f'' from ''/tmp/f.pyc''>,
''__file__'': ''/tmp/f.pyc'',
''__file__.split(os.path.sep)[-1]'': ''f.pyc'',
''os.path.abspath(__file__)'': ''/tmp/f.pyc''}
## on Windows ##
PS C:/tmp> python3.exe f.py
{''sys.modules[__name__]'': <module ''__main__'' from ''f.py''>,
''__file__'': ''f.py'',
''__file__.split(os.path.sep)[-1]'': ''f.py'',
''os.path.abspath(__file__)'': ''C://tools//cygwin//tmp//f.py''}
PS C:/tmp> python3.exe i.py
{''sys.modules[__name__]'': <module ''f'' from ''C://tools//cygwin//tmp//f.py''>,
''__file__'': ''C://tools//cygwin//tmp//f.py'',
''__file__.split(os.path.sep)[-1]'': ''f.py'',
''os.path.abspath(__file__)'': ''C://tools//cygwin//tmp//f.py''}
Si quieres quitar el ''.py'' del final, puedes hacerlo fácilmente. (Pero no olvides que puedes ejecutar un ''.pyc'' en su lugar).
Esto debería funcionar para hacer referencia al módulo actual:
import sys
sys.modules[__name__]
Ha pasado un tiempo desde que hice Python, pero creo que puedes obtener acceso a los usuarios globales y locales de una persona que llama a través de su traceback .
No creo que eso sea posible ya que está fuera del alcance de foo
. foo solo será consciente de su alcance interno, ya que puede ser llamado por innumerables módulos y aplicaciones.
Para obtener una referencia al módulo "__main__" cuando esté en otro:
import sys
sys.modules[''__main__'']
Para luego obtener la ruta del archivo del módulo, que incluye su nombre:
sys.modules[''__main__''].__file__
Si está dentro del módulo "__main__", simplemente use: __file__
Para obtener solo el nombre del archivo de la ruta del archivo:
import os
os.path.basename(file_path)
Para separar el nombre del archivo de su extensión:
file_name.split(".")[0]
Para obtener el nombre de una instancia de clase:
instance.__class__.__name__
Para obtener el nombre de una clase:
class.__name__
Si solo quieres el nombre del archivo:
file_name = __file__.split("/")[len(__file__.split("/"))-1]
__file__
es la ruta del módulo actual que se realiza la llamada.