Pregunta Recuperando la ruta del módulo de python


Quiero detectar si el módulo ha cambiado. Ahora, usar inotify es simple, solo necesita saber el directorio desde el que desea recibir las notificaciones.

¿Cómo recupero la ruta de un módulo en python?


526
2017-10-29 17:52


origen


Respuestas:


import a_module
print a_module.__file__

En realidad, le dará la ruta al archivo .pyc que se cargó, al menos en Mac OS X. Así que supongo que puede hacer

import os
path = os.path.dirname(amodule.__file__)

También puedes probar

path = os.path.abspath(amodule.__file__)

Para obtener el directorio para buscar cambios.


615
2017-10-29 23:57



Ahi esta inspect módulo en python.

Documentación oficial

El módulo de inspección proporciona varias funciones útiles para ayudar a obtener   información sobre objetos en vivo como módulos, clases, métodos,   funciones, tracebacks, objetos de marco y objetos de código. Por ejemplo,   puede ayudarte a examinar los contenidos de una clase, recuperar la fuente   código de un método, extraer y formatear la lista de argumentos para una función,   o obtenga toda la información que necesita para mostrar un rastreo detallado.

Ejemplo:

>>> import os
>>> import inspect
>>> inspect.getfile(os)
'/usr/lib64/python2.7/os.pyc'
>>> inspect.getfile(inspect)
'/usr/lib64/python2.7/inspect.pyc'
>>> os.path.dirname(inspect.getfile(inspect))
'/usr/lib64/python2.7'

190
2017-08-28 07:24



Como han dicho las otras respuestas, la mejor manera de hacerlo es con __file__ (demostrado de nuevo abajo). Sin embargo, hay una advertencia importante, que es que __file__ NO existe si está ejecutando el módulo por sí mismo (es decir, como __main__)

Por ejemplo, supongamos que tiene dos archivos (los cuales están en su PYTHONPATH):

#/path1/foo.py
import bar
print(bar.__file__)

y

#/path2/bar.py
import os
print(os.getcwd())
print(__file__)

Correr foo.py dará la salida:

/path1        # "import bar" causes the line "print(os.getcwd())" to run
/path2/bar.py # then "print(__file__)" runs
/path2/bar.py # then the import statement finishes and "print(bar.__file__)" runs

SIN EMBARGO, si intenta ejecutar bar.py por sí solo, obtendrá:

/path2                              # "print(os.getcwd())" still works fine
Traceback (most recent call last):  # but __file__ doesn't exist if bar.py is running as main
  File "/path2/bar.py", line 3, in <module>
    print(__file__)
NameError: name '__file__' is not defined 

Espero que esto ayude. Esta advertencia me costó mucho tiempo y confusión al probar las otras soluciones presentadas.


57
2018-06-20 19:05



Intentaré abordar algunas variaciones sobre esta pregunta también:

  1. encontrar la ruta del script llamado
  2. encontrar la ruta del script actualmente en ejecución
  3. encontrar el directorio del script llamado

(Algunas de estas preguntas se han pedido en SO, pero se han cerrado como duplicados y se han redireccionado aquí).

Advertencias de uso __file__

Para un módulo que ha importado:

import something
something.__file__ 

devolverá el absoluto camino del módulo. Sin embargo, dado el siguiente guión foo.py:

#foo.py
print '__file__', __file__

Llamarlo con 'python foo.py' Devolverá simplemente 'foo.py'. Si agrega un shebang:

#!/usr/bin/python 
#foo.py
print '__file__', __file__

y llamarlo usando ./foo.py, devolverá './foo.py'. Llamar desde un directorio diferente, (por ejemplo, poner foo.py en la barra de directorio), y luego llamar

python bar/foo.py

o agregando un shebang y ejecutando el archivo directamente:

bar/foo.py

devolverá 'bar / foo.py' (el relativo camino).

Encontrar el directorio

Ahora yendo desde allí para obtener el directorio, os.path.dirname(__file__) también puede ser complicado Al menos en mi sistema, devuelve una cadena vacía si la llamas desde el mismo directorio que el archivo. ex.

# foo.py
import os
print '__file__ is:', __file__
print 'os.path.dirname(__file__) is:', os.path.dirname(__file__)

dará salida:

__file__ is: foo.py
os.path.dirname(__file__) is: 

En otras palabras, devuelve una cadena vacía, por lo que no parece confiable si desea usarla para la corriente archivo (a diferencia de la archivo de un módulo importado). Para evitar esto, puede envolverlo en una llamada a abspath:

# foo.py
import os
print 'os.path.abspath(__file__) is:', os.path.abspath(__file__)
print 'os.path.dirname(os.path.abspath(__file__)) is:', os.path.dirname(os.path.abspath(__file__))

que produce algo así como:

os.path.abspath(__file__) is: /home/user/bar/foo.py
os.path.dirname(os.path.abspath(__file__)) is: /home/user/bar

Tenga en cuenta que abspath () NO resuelve enlaces simbólicos. Si desea hacer esto, use realpath () en su lugar. Por ejemplo, hacer un enlace simbólico file_import_testing_link apuntando a file_import_testing.py, con el siguiente contenido:

import os
print 'abspath(__file__)',os.path.abspath(__file__)
print 'realpath(__file__)',os.path.realpath(__file__)

la ejecución imprimirá rutas absolutas algo así como:

abspath(__file__) /home/user/file_test_link
realpath(__file__) /home/user/file_test.py

file_import_testing_link -> file_import_testing.py

Usando inspeccionar

@SummerBreeze menciona el uso de inspeccionar módulo.

Esto parece funcionar bien, y es bastante conciso, para los módulos importados:

import os
import inspect
print 'inspect.getfile(os) is:', inspect.getfile(os)

obedientemente devuelve el camino absoluto. Sin embargo, para encontrar la ruta del script en ejecución actualmente, no vi una forma de usarlo.


30
2018-05-30 02:15



No entiendo por qué nadie está hablando de esto, pero para mí la solución más simple es usar imp.find_module ("nombre del módulo") (documentación aquí)

import imp
imp.find_module("os")

Da una tupla con el camino en la segunda posición:

(<open file '/usr/lib/python2.7/os.py', mode 'U' at 0x7f44528d7540>,
'/usr/lib/python2.7/os.py',
('.py', 'U', 1))

La ventaja de este método sobre el de "inspección" es que no necesita importar el módulo para que funcione, y puede usar una cadena en la entrada. Útil al verificar módulos llamados en otro script, por ejemplo.

EDITAR:

En python3, importlib módulo debe hacer:

Doc de importlib.util.find_spec:

Devuelve la especificación para el módulo especificado.

En primer lugar, se comprueba sys.modules para ver si el módulo ya se importó. Si es así, entonces sys.modules [nombre].especulación es regresado. Si eso sucede ser   establecido en Ninguno, entonces ValueError se levanta. Si el módulo no está en   sys.modules, luego sys.meta_path se busca una especificación adecuada con el   valor de 'ruta' dada a los buscadores. No se devuelve ninguno si no se pudo espec   ser encontrado.

Si el nombre es para el submódulo (contiene un punto), el módulo principal es   importado automáticamente

Los argumentos de nombre y paquete funcionan igual que importlib.import_module ().   En otras palabras, los nombres relativos de los módulos (con puntos principales) funcionan.


18
2018-03-11 00:10



Esto fue trivial.

Cada módulo tiene una __file__ variable que muestra su ruta relativa desde donde se encuentra ahora.

Por lo tanto, obtener un directorio para que el módulo lo notifique es simple como:

os.path.dirname(__file__)

16
2017-10-29 19:18



import os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)

14
2017-12-13 17:35



Así que pasé una buena cantidad de tiempo intentando hacer esto con py2exe El problema era obtener la carpeta base del script, ya sea que se ejecutara como un script de python o como un ejecutable de py2exe. También para que funcione si se estaba ejecutando desde la carpeta actual, otra carpeta o (este fue el más difícil) desde la ruta del sistema.

Eventualmente utilicé este enfoque, usando sys.frozen como un indicador de ejecución en py2exe:

import os,sys
if hasattr(sys,'frozen'): # only when running in py2exe this exists
    base = sys.prefix
else: # otherwise this is a regular python script
    base = os.path.dirname(os.path.realpath(__file__))

6
2018-03-18 16:28



Utilidad de línea de comandos

Puede ajustarlo a una utilidad de línea de comandos,

python-which <package name>

enter image description here


Crear /usr/local/bin/python-which

#!/usr/bin/env python

import importlib
import os
import sys

args = sys.argv[1:]
if len(args) > 0:
    module = importlib.import_module(args[0])
    print os.path.dirname(module.__file__)

Hazlo ejecutable

sudo chmod +x /usr/local/bin/python-which

4
2017-08-15 16:27



import module
print module.__path__

Los paquetes admiten un atributo especial más, __path__. Esto es   inicializado para ser una lista que contiene el nombre del directorio que contiene   los paquetes __init__.py antes de que se ejecute el código en ese archivo.   Esta variable puede ser modificada; hacerlo afecta las búsquedas futuras de   módulos y subpaquetes contenidos en el paquete.

Si bien esta función no suele ser necesaria, se puede utilizar para ampliar   conjunto de módulos encontrados en un paquete.

Fuente


4
2017-08-16 23:04



Si la única advertencia de usar __file__ es cuando el directorio relativo actual está en blanco (es decir, cuando se ejecuta como un script desde el mismo directorio donde está el script), entonces una solución trivial es:

import os.path
mydir = os.path.dirname(__file__) or '.'
full  = os.path.abspath(mydir)
print __file__, mydir, full

Y el resultado:

$ python teste.py 
teste.py . /home/user/work/teste

El truco está en or '.' después de la dirname() llamada. Establece el directorio como ., lo que significa directorio actual y es un directorio válido para cualquier función relacionada con la ruta.

Por lo tanto, usando abspath() no es realmente necesario. Pero si lo usa de todos modos, el truco no es necesario: abspath() acepta rutas en blanco y las interpreta correctamente como el directorio actual.


2
2017-08-15 01:22