Domanda

Ho script che chiamano altri file di script ma devo ottenere il percorso del file attualmente in esecuzione all'interno del processo.

Ad esempio, diciamo che ho tre file.Utilizzando fileexe:

  • script_1.py chiamate script_2.py.
  • A sua volta, script_2.py chiamate script_3.py.

Come posso ottenere il nome e il percorso del file script_3.py, dal codice interno script_3.py, senza dover passare tali informazioni come argomenti da script_2.py?

(Eseguendo os.getcwd() restituisce il percorso file dello script iniziale originale e non quello del file corrente.)

È stato utile?

Soluzione

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

Altri suggerimenti

__file__

come altri hanno detto.Potresti anche voler utilizzare os.path.realpath per eliminare i collegamenti simbolici:

import os

os.path.realpath(__file__)

Aggiornamento 28-11-2018:

Ecco un riepilogo degli esperimenti con Python 2 e 3.Con

main.py: esegue foo.py
foo.py: esegue lib/bar.py
lib/bar.py - stampa le espressioni del percorso file

| 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__                               |

Per Python 2, potrebbe essere più chiaro passare ai pacchetti so can use from lib import bar - basta aggiungere vuoto __init__.py file nelle due cartelle.

Per Python 3, execfile non esiste: l'alternativa più vicina è exec(open(<filename>).read()), sebbene ciò influisca sugli stack frame.È più semplice da usare import foo E import lib.bar - NO __init__.py file necessari.

Guarda anche Differenza tra import ed execfile


Risposta originale:

Ecco un esperimento basato sulle risposte in questo thread - con Python 2.7.10 su Windows.

Quelli basati sullo stack sono gli unici che sembrano fornire risultati affidabili.Gli ultimi due hanno la sintassi più breve, cioè.-

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

Ecco a questi che vengono aggiunti sistema come funzioni!Ringraziamo @Usagi e @pablog

Basato sui seguenti tre file ed eseguendo main.py dalla sua cartella con python main.py (ho provato anche file exec con percorsi assoluti e chiamate da una cartella separata).

C:\percorsifile\main.py: execfile('foo.py')
C:\percorsifile\foo.py: execfile('lib/bar.py')
C:\percorsifile\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

Penso che questo sia più pulito:

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

e ottiene le stesse informazioni di:

print inspect.getfile(inspect.currentframe())

Dove [0] è il fotogramma corrente nello stack (in cima allo stack) e [1] è per il nome del file, aumentare per tornare indietro nello stack, ad es.

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

sarebbe il nome del file dello script che ha chiamato il frame corrente.Inoltre, l'utilizzo di [-1] ti porterà in fondo allo stack, lo script di chiamata originale.

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

I suggerimenti contrassegnati come migliori sono tutti veri se lo script è costituito da un solo file.

Se vuoi scoprire il nome dell'eseguibile (es.il file root passato all'interprete Python per il programma corrente) da un file che può essere importato come modulo, è necessario eseguire questa operazione (supponiamo che sia in un file denominato foo.py):

import inspect

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

Perché l'ultima cosa ([-1]) nello stack è la prima cosa che è stata inserita (gli stack sono strutture dati LIFO/FILO).

Poi in archivio bar.py se tu import foo verrà stampato bar.py, piuttosto che foo.py, che sarebbe il valore di tutti questi:

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

questo ci darà solo il nome del file.cioè.se il percorso abspath del file è c:\abcd\abc.py la seconda riga stamperà abc.py

Non è del tutto chiaro cosa intendi con "il percorso del file attualmente in esecuzione all'interno del processo".sys.argv[0] solitamente contiene la posizione dello script invocato dall'interprete Python.Controlla il documentazione di sistema per ulteriori dettagli.

Come hanno sottolineato @Tim e @Pat Notz, l'attributo __file__ fornisce l'accesso a

il file da cui è stato caricato il modulo, se è stato caricato da un file

Ho uno script che deve funzionare in ambiente Windows.Questo codice snipped è quello con cui ho finito:

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

è una decisione piuttosto complicata.Ma non richiede librerie esterne ed è la cosa più importante nel mio caso.

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

Non c'è bisogno di ispezionare o di qualsiasi altra libreria.

Questo ha funzionato per me quando dovevo importare uno script (da una directory diversa dallo script eseguito), che utilizzava un file di configurazione residente nella stessa cartella dello script importato.

IL __file__ L'attributo funziona sia per il file contenente il codice di esecuzione principale che per i moduli importati.

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

import sys

print sys.path[0]

questo stamperebbe il percorso dello script attualmente in esecuzione

Penso che sia giusto __file__ Sembra che potresti voler controllare anche il ispezionare il modulo.

Puoi usare 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'

Prova questo,

import os
os.path.dirname(os.path.realpath(__file__))
import sys
print sys.argv[0]

Questo dovrebbe funzionare:

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

Per ottenere la directory di esecuzione dello script

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

Per mantenere la coerenza della migrazione tra piattaforme (macOS/Windows/Linux), prova:

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

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

Ho usato l'approccio con __file__
os.path.abspath(__file__)
Ma c'è un piccolo trucco, restituisce il file .py quando il codice viene eseguito la prima volta, le esecuzioni successive forniscono il nome del file *.pyc
quindi sono rimasto con:
inspect.getfile(inspect.currentframe())
O
sys._getframe().f_code.co_filename

Ho scritto una funzione che tiene conto dell'eclissi debugger E unittest.Restituisce la cartella del primo script che avvii.Facoltativamente è possibile specificare il file __file__ var, ma la cosa principale è che non devi condividere questa variabile tra tutti i tuoi file gerarchia delle chiamate.

Forse puoi gestire altri casi particolari che non ho visto, ma per me va bene.

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

Il modo più semplice è:

In script_1.py:

import subprocess
subprocess.call(['python3',<path_to_script_2.py>])

In script_2.py:

sys.argv[0]

PS:ho provato execfile, ma poiché legge script_2.py come una stringa, sys.argv[0] restituito <string>.

Ho sempre utilizzato solo la funzionalità del sistema operativo di Current Working Directory o CWD.Questo fa parte della libreria standard ed è molto facile da implementare.Ecco un esempio:

    import os
    base_directory = os.getcwd()

La maggior parte di queste risposte sono state scritte in Python versione 2.x o precedente.In Python 3.x la sintassi per la funzione print è cambiata per richiedere parentesi, cioèstampa().

Quindi, questa precedente risposta con punteggio elevato da user13993 in 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

Diventa in 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

se vuoi solo il nome del file senza ./ O .py puoi provare questo

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

file_name Stamperai testScript che puoi generare quello che vuoi modificando l'indice all'interno [

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)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top