Risposte:
È possibile utilizzare __file__
per ottenere il nome del file corrente. Se utilizzato nel modulo principale, questo è il nome dello script originariamente richiamato.
Se si desidera omettere la parte della directory (che potrebbe essere presente), è possibile utilizzare os.path.basename(__file__)
.
__file__
non è definito nell'interprete interattivo, perché lì non ha senso. È impostato dall'implementazione di importazione, quindi se si utilizza un meccanismo di importazione non standard potrebbe anche non essere impostato.
import os
sia necessario per farlo funzionare. Aggiungerei questo nella risposta.
import os
e import os.path
sono completamente equivalenti.
import sys
print sys.argv[0]
Questo verrà stampato foo.py
per python foo.py
, dir/foo.py
per python dir/foo.py
, ecc. È il primo argomento a python
. (Nota che dopo py2exe lo sarebbe foo.exe
.)
python linkfile.py
, dove si linkfile.py
trova un collegamento simbolico realfile.py
, sys.argv[0]
sarà 'linkfile.py'
, che può essere o meno quello che vuoi; è certamente quello che mi aspetto . __file__
è lo stesso: lo sarà linkfile.py
. Se vuoi trovare 'realfile.py'
da 'linkfile.py'
, prova os.path.realpath('linkfile.py')
.
__file__
invece.
Per completezza, ho pensato che sarebbe utile riassumere i vari risultati possibili e fornire riferimenti per il comportamento esatto di ciascuno:
__file__
è il file attualmente in esecuzione, come dettagliato nella documentazione ufficiale :
__file__
è il percorso del file da cui è stato caricato il modulo, se è stato caricato da un file. L'__file__
attributo potrebbe mancare per alcuni tipi di moduli, come i moduli C che sono staticamente collegati all'interprete; per i moduli di estensione caricati dinamicamente da una libreria condivisa, è il percorso del file della libreria condivisa.
Da Python3.4 in poi, per il numero 18416 , __file__
è sempre un percorso assoluto, a meno che il file attualmente in esecuzione sia uno script che è stato eseguito direttamente (non tramite l'interprete con l' -m
opzione della riga di comando) usando un percorso relativo.
__main__.__file__
(richiede l'importazione __main__
) accede semplicemente __file__
all'attributo sopra menzionato del modulo principale , ad esempio dello script che è stato invocato dalla riga di comando.
sys.argv[0]
(richiede l'importazione sys
) è il nome dello script che è stato invocato dalla riga di comando e potrebbe essere un percorso assoluto, come dettagliato nella documentazione ufficiale :
argv[0]
è il nome dello script (dipende dal sistema operativo se si tratta di un percorso completo o meno). Se il comando è stato eseguito utilizzando l'-c
opzione della riga di comando per l'interprete,argv[0]
è impostato sulla stringa'-c'
. Se nessun nome di script è stato passato all'interprete Python,argv[0]
è la stringa vuota.
Come menzionato in un'altra risposta a questa domanda , gli script Python che sono stati convertiti in programmi eseguibili autonomi tramite strumenti come py2exe o PyInstaller potrebbero non visualizzare il risultato desiderato quando si utilizza questo approccio (ad esempio, sys.argv[0]
conterrebbe il nome dell'eseguibile anziché il nome del file Python principale all'interno dell'eseguibile).
Se nessuna delle opzioni sopra menzionate sembra funzionare, probabilmente a causa di un'operazione di importazione irregolare, il modulo di ispezione potrebbe rivelarsi utile. In particolare, invocare inspect.getfile(...)
su inspect.currentframe()
potrebbe funzionare, sebbene quest'ultimo ritorniNone
quando viene eseguito in un'implementazione senza frame stack Python .
Se lo script corrente è un collegamento simbolico, tutto quanto sopra restituirà il percorso del collegamento simbolico anziché il percorso del file reale e os.path.realpath(...)
dovrebbe essere invocato per estrarre quest'ultimo.
os.path.basename(...)
può essere invocato su uno dei precedenti per estrarre il nome file effettivo e os.path.splitext(...)
può essere richiamato sul nome file effettivo per troncarne il suffisso, come inos.path.splitext(os.path.basename(...))
.
Da Python 3.4 in poi, secondo PEP 428 , la PurePath
classe del pathlib
modulo può essere usata anche su uno dei precedenti. In particolare, pathlib.PurePath(...).name
estrae il nome del file effettivo ed pathlib.PurePath(...).stem
estrae il nome del file effettivo senza il suo suffisso.
Si noti che __file__
fornirà il file in cui risiede questo codice, che può essere importato e diverso dal file principale da interpretare. Per ottenere il file principale, è possibile utilizzare il modulo __main__ speciale :
import __main__ as main
print(main.__file__)
Nota che __main__.__file__
funziona in Python 2.7 ma non in 3.2, quindi usa la sintassi import-as come sopra per renderla portatile.
rPython
pacchetto dalla R
lingua. Deve essere un caso eccezionale che è troppo difficile da gestire.
__main__
internamente, per l'uso nel passare variabili tra R
e python
, quindi sarebbe relativamente facile impostarlo __main__.__file__
prima di chiamare qualsiasi altra cosa, ma non sono nemmeno sicuro di quale valore sarebbe appropriato in questo caso.
Le risposte sopra sono buone. Ma ho trovato questo metodo più efficiente usando i risultati sopra.
Ciò comporta che il nome del file di script effettivo non è un percorso.
import sys
import os
file_name = os.path.basename(sys.argv[0])
Per le moderne versioni di Python (3.4+), Path(__file__).name
dovrebbe essere più idiomatico. Inoltre, Path(__file__).stem
ti dà il nome dello script senza l' .py
estensione.
from pathlib import Path
prima.
pathlib
stato introdotto in Python 3.4, quindi dovrebbe funzionare a partire da Python 3.4.
Supponendo che il nome file sia foo.py
, lo snippet di seguito
import sys
print sys.argv[0][:-3]
o
import sys
print sys.argv[0][::-1][3:][::-1]
Come per altre estensioni con più caratteri, ad esempio il nome file foo.pypy
import sys
print sys.argv[0].split('.')[0]
Se si desidera estrarre da un percorso assoluto
import sys
print sys.argv[0].split('/')[-1].split('.')[0]
uscirà foo
Il primo argomento in sys sarà il nome del file corrente, quindi funzionerà
import sys
print sys.argv[0] # will print the file name
Se stai eseguendo un'importazione insolita (ad esempio, è un file di opzioni), prova:
import inspect
print (inspect.getfile(inspect.currentframe()))
Si noti che questo restituirà il percorso assoluto al file.
possiamo provare questo per ottenere il nome dello script corrente senza estensione.
import os
script_name = os.path.splitext(os.path.basename(__file__))[0]
tutte le risposte sono fantastiche, ma hanno alcuni problemi Potresti non vedere a prima vista.
definiamo ciò che vogliamo - vogliamo il nome dello script che è stato eseguito, non il nome del modulo corrente - quindi __file__
funzionerà solo se viene utilizzato nello script eseguito, non in un modulo importato.
sys.argv
è anche discutibile: cosa succede se il tuo programma è stato chiamato da Pytest? o corridore pydoc? o se è stato chiamato da uwsgi?
e - esiste un terzo metodo per ottenere il nome dello script, non ho visto nelle risposte - È possibile controllare lo stack.
Un altro problema è che tu (o qualche altro programma) puoi manomettere sys.argv
e__main__.__file__
- potrebbe essere presente, potrebbe non esserlo. Potrebbe essere valido o no. Almeno puoi verificare se esiste lo script (il risultato desiderato)!
la mia libreria bitranox / lib_programname su github fa esattamente questo:
__main__
è presente__main__.__file__
è presente__main__.__file__
un risultato valido (esiste quello script?)per quella via, la mia soluzione sta lavorando finora con setup.py test
, uwsgi
, pytest
, pycharm pytest
, pycharm docrunner (doctest)
, dreampie
,eclipse
c'è anche un bell'articolo sul blog su quel problema di Dough Hellman, "Determinare il nome di un processo da Python"
La mia soluzione sporca veloce:
__file__.split('/')[-1:][0]
os.path
per dividere i nomi dei file
os.path.abspath(__file__)
ti darà un percorso assoluto ( relpath()
disponibile anche).
sys.argv[-1]
ti darà un percorso relativo.
A partire da Python 3.5 puoi semplicemente fare:
from pathlib import Path
Path(__file__).stem
Vedi di più qui: https://docs.python.org/3.5/library/pathlib.html#pathlib.PurePath.stem
Ad esempio, ho un file nella mia directory utente chiamato test.py
con questo all'interno:
from pathlib import Path
print(Path(__file__).stem)
print(__file__)
eseguendo questo output:
>>> python3.6 test.py
test
test.py
Exception NameError: NameError("global name '__file__' is not defined",)
"