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

StackOverflow https://stackoverflow.com/questions/50499

  •  09-06-2019
  •  | 
  •  

Pregunta

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

Por ejemplo, digamos que tengo tres archivos.Usando archivo ejecutable:

  • script_1.py llamadas script_2.py.
  • Sucesivamente, script_2.py llamadas script_3.py.

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

(Ejecutando os.getcwd() devuelve la ruta del archivo del script de inicio original, no la del archivo actual).

¿Fue útil?

Solución

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

Otros consejos

__file__

como han dicho otros.Es posible que también desee utilizar os.ruta.rutareal 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 para poder usar from lib import bar - solo agrega vacío __init__.py archivos a las dos carpetas.

Para Python 3, execfile no existe - la alternativa más cercana es exec(open(<filename>).read()), aunque esto afecta los marcos de la pila.Lo más sencillo es simplemente utilizar import foo y import lib.bar - No __init__.py archivos necesarios.

Ver también Diferencia entre importar y ejecutar


Respuesta original:

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

Los basados ​​en pilas son los únicos que parecen dar resultados fiables.Los dos últimos tienen la sintaxis 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

Por estos que se agregan a sistema 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é archivos exec con rutas absolutas y llamadas desde una carpeta separada).

C: utas de archivos\main.py: execfile('foo.py')
C: utas de archivos\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 fotograma actual en la pila (parte superior de la pila) y [1] es el nombre del archivo, aumente para retroceder en la pila, es decir,

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

sería el nombre de archivo del script que llamó al fotograma actual.Además, usar [-1] lo llevará al final de la pila, 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 programa actual) desde un archivo que puede importarse como un módulo, debe hacer esto (supongamos que esto está en un archivo llamado foo.py):

import inspect

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

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

Luego en el archivo bar.py si usted import foo se imprimirá bar.py, en vez 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 entonces la segunda línea imprimirá abc.py

No está del todo claro qué quiere decir con "la ruta del archivo que se está ejecutando actualmente dentro del proceso".sys.argv[0] normalmente contiene la ubicación del script que fue invocado por el intérprete de Python.Comprobar el 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 cual se cargó el módulo, si se cargó desde un archivo

Tengo un script que debe funcionar en un entorno Windows.Este código recortado es con lo que terminé:

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

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

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

No es necesario inspeccionar ni ninguna otra biblioteca.

Esto funcionó para mí 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 __file__ El atributo 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 es posible que también quieras consultar el inspeccionar el módulo.

Puedes usar inspect.stack()

import inspect,os
inspect.stack()[0]  => (<frame object at 0x00AC2AC0>, 'g:\\Python\\Test\\_GetCurrentProgram.py', 15, '<module>', ['print inspect.stack()[0]\n'], 0)
os.path.abspath (inspect.stack()[0][1]) => 'g:\\Python\\Test\\_GetCurrentProgram.py'

Prueba esto,

import os
os.path.dirname(os.path.realpath(__file__))
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 del script en ejecución

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

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

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

print(__file__)
print(__import__("pathlib").Path(__file__).parent)

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

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

Tal vez puedas manejar otros casos particulares 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',<path_to_script_2.py>])

en script_2.py:

sys.argv[0]

PD.:He intentado execfile, pero como lee script_2.py como una cadena, sys.argv[0] regresó <string>.

Siempre he usado la función del sistema operativo Current Working Directory 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 se escribieron en la versión 2.x de Python o anterior.En Python 3.x, la sintaxis de la función de impresión ha cambiado para requerir paréntesis, es decirimprimir().

Entonces, esta respuesta anterior de puntuación alta del usuario13993 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 quieres solo el nombre del archivo sin ./ o .py puedes probar esto

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

file_name Imprimirá TestScript, puede generar lo que desee cambiando el índice dentro [

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)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top