¿Cómo obtengo la ruta y el nombre del archivo que se está ejecutando actualmente?

Tengo scripts que llaman a otros archivos de script, pero necesito obtener la ruta de archivo del archivo que se está ejecutando actualmente dentro del proceso.

Por ejemplo, digamos que tengo tres archivos. Utilizando execfile :

  • script_1.py llama a script_2.py .
  • A su vez, script_2.py llama a script_3.py .

¿Cómo puedo obtener el nombre de archivo y la ruta de script_3.py , desde el código dentro de script_3.py , sin tener que pasar esa información como argumentos de script_2.py ?

(La ejecución de os.getcwd() devuelve la os.getcwd() de archivo del script de inicio original, no la del archivo actual).

p1.py:

 execfile("p2.py") 

p2.py:

 import inspect, os print inspect.getfile(inspect.currentframe()) # script filename (usually with path) print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # script directory 
 __file__ 

como han dicho otros. También es posible que desee utilizar os.path.realpath para eliminar enlaces simbólicos:

 import os os.path.realpath(__file__) 

Actualización 2018-11-28:

Aquí hay un resumen de los experimentos con Python 2 y 3. Con

main.py – ejecuta foo.py
foo.py – ejecuta lib / bar.py
lib / bar.py – imprime expresiones de ruta de archivo

 | Python | Run statement | Filepath expression | |--------+---------------------+----------------------------------------| | 2 | execfile | os.path.abspath(inspect.stack()[0][1]) | | 2 | from lib import bar | __file__ | | 3 | exec | (wasn't able to obtain it) | | 3 | import lib.bar | __file__ | 

Para Python 2, podría ser más claro cambiar a paquetes, así que puede usarlos from lib import bar . Simplemente agregue archivos __init__.py vacíos a las dos carpetas.

Para Python 3, execfile no existe, la alternativa más cercana es exec(open().read()) execfile exec(open().read()) , aunque esto afecta a los marcos de la stack. Es más simple usar solo import foo e import lib.bar , no se necesitan archivos __init__.py .

Ver también Diferencia entre importación y execfile.


Respuesta original:

Aquí hay un experimento basado en las respuestas de este hilo, con Python 2.7.10 en Windows.

Los basados ​​en stack son los únicos que parecen dar resultados confiables. Los dos últimos tienen la syntax más corta , es decir:

 print os.path.abspath(inspect.stack()[0][1]) # C:\filepaths\lib\bar.py print os.path.dirname(os.path.abspath(inspect.stack()[0][1])) # C:\filepaths\lib 

¡A estos se añaden a sys como funciones! Crédito a @Usagi y @pablog

Basado en los siguientes tres archivos, y ejecutando main.py desde su carpeta con python main.py (también probé execfiles con rutas absolutas y llamadas desde una carpeta separada).

C: \ filepaths \ main.py: execfile('foo.py')
C: \ filepaths \ foo.py: execfile('lib/bar.py')
C: \ filepaths \ lib \ bar.py:

 import sys import os import inspect print "Python " + sys.version print print __file__ # main.py print sys.argv[0] # main.py print inspect.stack()[0][1] # lib/bar.py print sys.path[0] # C:\filepaths print print os.path.realpath(__file__) # C:\filepaths\main.py print os.path.abspath(__file__) # C:\filepaths\main.py print os.path.basename(__file__) # main.py print os.path.basename(os.path.realpath(sys.argv[0])) # main.py print print sys.path[0] # C:\filepaths print os.path.abspath(os.path.split(sys.argv[0])[0]) # C:\filepaths print os.path.dirname(os.path.abspath(__file__)) # C:\filepaths print os.path.dirname(os.path.realpath(sys.argv[0])) # C:\filepaths print os.path.dirname(__file__) # (empty string) print print inspect.getfile(inspect.currentframe()) # lib/bar.py print os.path.abspath(inspect.getfile(inspect.currentframe())) # C:\filepaths\lib\bar.py print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # C:\filepaths\lib print print os.path.abspath(inspect.stack()[0][1]) # C:\filepaths\lib\bar.py print os.path.dirname(os.path.abspath(inspect.stack()[0][1])) # C:\filepaths\lib print 

Creo que esto es más limpio:

 import inspect print inspect.stack()[0][1] 

y obtiene la misma información que:

 print inspect.getfile(inspect.currentframe()) 

Donde [0] es el fotogtwig actual en la stack (parte superior de la stack) y [1] es para el nombre del archivo, boost para ir hacia atrás en la stack, es decir

 print inspect.stack()[1][1] 

sería el nombre de archivo de la secuencia de comandos que llamó al marco actual. Además, el uso de [-1] lo llevará al final de la stack, el script de llamada original.

 import os os.path.dirname(__file__) # relative directory path os.path.abspath(__file__) # absolute file path os.path.basename(__file__) # the file name only 

Las sugerencias marcadas como mejores son todas verdaderas si su secuencia de comandos consta de un solo archivo.

Si desea averiguar el nombre del ejecutable (es decir, el archivo raíz pasado al intérprete de python para el progtwig actual) desde un archivo que puede importarse como un módulo, debe hacer esto (supongamos que se trata de un archivo llamado foo.py ):

import inspect

print inspect.stack()[-1][1]

Porque lo último ( [-1] ) en la stack es lo primero que entró (las stacks son estructuras de datos LIFO / FILO).

Luego, en el archivo bar.py, si import foo , imprimirá bar.py , en lugar de foo.py , que sería el valor de todos estos:

  • __file__
  • inspect.getfile(inspect.currentframe())
  • inspect.stack()[0][1]
 import os print os.path.basename(__file__) 

Esto nos dará solo el nombre del archivo. es decir, si abspath del archivo es c: \ abcd \ abc.py, la segunda línea se imprimirá abc.py

No está del todo claro a qué se refiere con “la ruta de archivo del archivo que se está ejecutando actualmente dentro del proceso”. sys.argv[0] generalmente contiene la ubicación del script que fue invocado por el intérprete de Python. Consulte la documentación del sistema para más detalles.

Como han señalado @Tim y @Pat Notz, el atributo __file__ proporciona acceso a

el archivo desde el que se cargó el módulo, si se cargó desde un archivo

Tengo un script que debe funcionar en el entorno de Windows. Este código cortado es lo que he terminado con:

 import os,sys PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0]) 

Es una decisión bastante difícil. Pero no requiere bibliotecas externas y es lo más importante en mi caso.

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

No hay necesidad de inspeccionar o cualquier otra biblioteca.

Esto me funcionó cuando tuve que importar un script (desde un directorio diferente al script ejecutado), que usaba un archivo de configuración que residía en la misma carpeta que el script importado.

El atributo __file__ funciona tanto para el archivo que contiene el código de ejecución principal como para los módulos importados.

Ver https://web.archive.org/web/20090918095828/http://pyref.infogami.com/__file__

 import sys print sys.path[0] 

Esto imprimiría la ruta del script que se está ejecutando actualmente.

Creo que es solo __file__ Parece que también puede querer revisar el módulo de inspección .

Puedes usar inspect.stack()

 import inspect,os inspect.stack()[0] => (, 'g:\\Python\\Test\\_GetCurrentProgram.py', 15, '', ['print inspect.stack()[0]\n'], 0) os.path.abspath (inspect.stack()[0][1]) => 'g:\\Python\\Test\\_GetCurrentProgram.py' 
 import sys print sys.argv[0] 

Esto debería funcionar:

 import os,sys filename=os.path.basename(os.path.realpath(sys.argv[0])) dirname=os.path.dirname(os.path.realpath(sys.argv[0])) 

Para obtener el directorio de ejecución de script

  print os.path.dirname( inspect.getfile(inspect.currentframe())) 

Para mantener la coherencia de la migración en todas las plataformas (macOS / Windows / Linux), intente:

path = r'%s' % os.getcwd().replace('\\','/')

Prueba esto,

 import os os.path.dirname(os.path.realpath(__file__)) 

Utilicé el enfoque con __file__
os.path.abspath(__file__)
pero hay un pequeño truco, devuelve el archivo .py cuando se ejecuta el código la primera vez, las siguientes ejecuciones dan el nombre del archivo * .pyc
así que me quedé con:
inspect.getfile(inspect.currentframe())
o
sys._getframe().f_code.co_filename

Escribí una función que tiene en cuenta el depurador de eclipse y la prueba de unidad . Devuelve la carpeta del primer script que inicie. Opcionalmente, puede especificar __file__ var, pero lo principal es que no tiene que compartir esta variable en toda su jerarquía de llamadas .

Tal vez puedas manejar otros casos de stack que no vi, pero para mí está bien.

 import inspect, os def getRootDirectory(_file_=None): """ Get the directory of the root execution file Can help: http://stackoverflow.com/questions/50499/how-do-i-get-the-path-and-name-of-the-file-that-is-currently-executing For eclipse user with unittest or debugger, the function search for the correct folder in the stack You can pass __file__ (with 4 underscores) if you want the caller directory """ # If we don't have the __file__ : if _file_ is None: # We get the last : rootFile = inspect.stack()[-1][1] folder = os.path.abspath(rootFile) # If we use unittest : if ("/pysrc" in folder) & ("org.python.pydev" in folder): previous = None # We search from left to right the case.py : for el in inspect.stack(): currentFile = os.path.abspath(el[1]) if ("unittest/case.py" in currentFile) | ("org.python.pydev" in currentFile): break previous = currentFile folder = previous # We return the folder : return os.path.dirname(folder) else: # We return the folder according to specified __file__ : return os.path.dirname(os.path.realpath(_file_)) 

La forma más sencilla es:

en script_1.py:

 import subprocess subprocess.call(['python3',]) 

en script_2.py:

 sys.argv[0] 

PD: he intentado execfile , pero como lee script_2.py como una cadena, sys.argv[0] devolvió .

Siempre he usado la función os del Directorio de trabajo actual, o CWD. Esto es parte de la biblioteca estándar y es muy fácil de implementar. Aquí hay un ejemplo:

  import os base_directory = os.getcwd() 

La mayoría de estas respuestas fueron escritas en Python versión 2.xo anterior. En Python 3.x, la syntax de la función de impresión ha cambiado para requerir paréntesis, es decir, print ().

Entonces, esta respuesta de puntuación más alta del usuario 13993 en Python 2.x:

 import inspect, os print inspect.getfile(inspect.currentframe()) # script filename (usually with path) print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # script directory 

Se convierte en Python 3.x:

 import inspect, os print(inspect.getfile(inspect.currentframe())) # script filename (usually with path) print(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) ) # script directory 

Si solo desea el nombre de archivo sin ./ o .py , puede intentar esto

 filename = testscript.py file_name = __file__[2:-3] 

file_name imprimirá el script de prueba que puede generar lo que quiera cambiando el índice dentro de []

 import os import wx # return the full path of this file print(os.getcwd()) icon = wx.Icon(os.getcwd() + '/img/image.png', wx.BITMAP_TYPE_PNG, 16, 16) # put the icon on the frame self.SetIcon(icon)