Ottieni il nome dello script corrente in Python


408

Sto cercando di ottenere il nome dello script Python attualmente in esecuzione.

Ho uno script chiamato foo.pye mi piacerebbe fare qualcosa del genere per ottenere il nome dello script:

print Scriptname

Risposte:


621

È 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__).


15
Python 3.2: " Exception NameError: NameError("global name '__file__' is not defined",)"
sdaau,

20
@sdaau: __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.
Sven Marnach,

8
Almeno per Python 2.7, credo che import ossia necessario per farlo funzionare. Aggiungerei questo nella risposta.
Nick Chammas,

14
@ cdunn2001: import ose import os.pathsono completamente equivalenti.
Sven Marnach,

2
@ sven-marnach: Oh, hai ragione . Lo sto facendo male da anni!
cdunn2001,

136
import sys
print sys.argv[0]

Questo verrà stampato foo.pyper python foo.py, dir/foo.pyper python dir/foo.py, ecc. È il primo argomento a python. (Nota che dopo py2exe lo sarebbe foo.exe.)


33
@DenisMalinovsky: definisci "non funzionerà". Se chiami python linkfile.py, dove si linkfile.pytrova 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').
Chris Morgan,

6
+1 perché è (a) un po 'più ordinato e (b) funzionerà ancora nel modulo (dove la variabile del file sarebbe il file del modulo, non quello eseguito).
Robert

Questa risposta è buona perché funziona anche in IDLE. Come nota, per ottenere solo il nome del file, puoi scrivere os.path.basename (sys.argv [0])
Steven Bluen,

Ancora più importante, questo non funziona se non dall'interno del file principale. Non usare questo, usa __file__invece.
Apollys sostiene Monica il

CHE COSA!!! Ci hai provato? È vero esattamente il contrario. L'interrogante ha chiesto il nome dello script python in esecuzione, non il file python attualmente in esecuzione. Immagina di avere uno script che, quando si verifica un errore, stampa il nome dello script insieme agli argomenti consentiti. Lo metti in una funzione, usando una di queste 2 tecniche. Ad un certo punto, decidi di spostare la funzione in una libreria esterna. Desideri stampare il nome dello script principale in esecuzione o il nome del file della libreria in esecuzione?
John Deighan,

71

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' -mopzione 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' -copzione 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 .


Gestione dei collegamenti simbolici

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.


Ulteriori manipolazioni che estraggono il nome del file effettivo

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 PurePathclasse del pathlibmodulo può essere usata anche su uno dei precedenti. In particolare, pathlib.PurePath(...).nameestrae il nome del file effettivo ed pathlib.PurePath(...).stemestrae il nome del file effettivo senza il suo suffisso.


66

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.


Questo funziona in molti casi, ma non quando sto usando il rPythonpacchetto dalla Rlingua. Deve essere un caso eccezionale che è troppo difficile da gestire.
Leonid,

In effetti, il pacchetto rPython incorpora l'interprete python, il che significa che non esiste un file 'principale' come c'è quando python è in esecuzione da solo (troverai lo stesso comportamento ogni volta che python è incorporato). Importa __main__internamente, per l'uso nel passare variabili tra Re 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.
Perkins,

42

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

1
Mi piace anche dividere l'estensione, quindi uso: os.path.splitext (os.path.basename (sys.argv [0])) [0]
RufusVS

19

Per le moderne versioni di Python (3.4+), Path(__file__).namedovrebbe essere più idiomatico. Inoltre, Path(__file__).stemti dà il nome dello script senza l' .pyestensione.


NameError: il nome 'Path' non è definito
RufusVS

5
Dovresti from pathlib import Pathprima.
Emil Melnikov,

"moderno" significa Python 3.x?
einpoklum,

1
@einpoklum è pathlibstato introdotto in Python 3.4, quindi dovrebbe funzionare a partire da Python 3.4.
Andrey Semakin,


9

Nota: se si utilizza Python 3+, è necessario utilizzare invece la funzione print ()

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


1
sys.argv [0] [: - 3] farebbe
kon psych il

@konpsych è più elegante
xtonousou,

C'è grande differenza tra __file__e sys.argv[0], vedere stackoverflow.com/questions/5851588/...
Maksym Ganenko

8

Il primo argomento in sys sarà il nome del file corrente, quindi funzionerà

   import sys
   print sys.argv[0] # will print the file name

7

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.


3

possiamo provare questo per ottenere il nome dello script corrente senza estensione.

import os

script_name = os.path.splitext(os.path.basename(__file__))[0]

2

Dal momento che l'OP ha chiesto il nome del file di script corrente, preferirei

import os
os.path.split(sys.argv[0])[1]

1

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.argve__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:

  • controlla se __main__è presente
  • controlla se __main__.__file__è presente
  • __main__.__file__un risultato valido (esiste quello script?)
  • in caso contrario: controlla sys.argv:
  • c'è pytest, docrunner, ecc. in sys.argv? -> se sì, ignoralo
  • possiamo ottenere un risultato valido qui?
  • in caso contrario: ispezionare lo stack e ottenere il risultato da lì possibilmente
  • se anche lo stack non fornisce un risultato valido, quindi genera un'eccezione.

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"


0

La mia soluzione sporca veloce:

__file__.split('/')[-1:][0]

2
Meglio usare os.pathper dividere i nomi dei file
Maksym Ganenko,


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.