Obtenir le nom du script actuel en Python


408

J'essaie d'obtenir le nom du script Python en cours d'exécution.

J'ai un script appelé foo.pyet j'aimerais faire quelque chose comme ça afin d'obtenir le nom du script:

print Scriptname

Réponses:


621

Vous pouvez utiliser __file__pour obtenir le nom du fichier actuel. Lorsqu'il est utilisé dans le module principal, il s'agit du nom du script qui a été initialement appelé.

Si vous souhaitez omettre la partie répertoire (qui peut être présente), vous pouvez utiliser os.path.basename(__file__).


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

20
@sdaau: __file__n'est pas défini dans l'interpréteur interactif, car il n'a pas de sens là-bas. Il est défini par l'implémentation d'importation, donc si vous utilisez un mécanisme d'importation non standard, il peut également ne pas être défini.
Sven Marnach

8
Au moins pour Python 2.7, je crois qu'un import osest requis pour que cela fonctionne. J'ajouterais ceci dans la réponse.
Nick Chammas

14
@ cdunn2001: import oset import os.pathsont complètement équivalents.
Sven Marnach

2
@ sven-marnach: Oh, tu as raison . Je le fais mal depuis des années!
cdunn2001

136
import sys
print sys.argv[0]

Cela s'imprimera foo.pypour python foo.py, dir/foo.pypour python dir/foo.py, etc. C'est le premier argument de python. (Notez qu'après py2exe, ce serait le cas foo.exe.)


33
@DenisMalinovsky: définissez "ne fonctionnera pas". Si vous appelez python linkfile.py, où linkfile.pyest un lien symbolique vers realfile.py, sys.argv[0]sera 'linkfile.py', qui peut ou non être ce que vous voulez; c'est certainement ce que j'attends . __file__c'est pareil: ça le sera linkfile.py. Si vous souhaitez rechercher à 'realfile.py'partir de 'linkfile.py', essayez os.path.realpath('linkfile.py').
Chris Morgan

6
+1 parce que c'est (a) un peu plus propre et (b) fonctionnera toujours dans le module (où la variable de fichier serait le fichier de module, pas celui exécuté).
robert

Cette réponse est agréable car elle fonctionne également en mode IDLE. Remarque: pour obtenir uniquement le nom du fichier, vous pouvez écrire os.path.basename (sys.argv [0])
Steven Bluen

Plus important encore, cela ne fonctionne que depuis l'intérieur du fichier principal. Ne l'utilisez pas, utilisez __file__plutôt.
Apollys prend en charge Monica le

QUOI!!! Avez-vous même essayé cela? C'est exactement le contraire qui est vrai. L'interrogateur a demandé le nom du script python en cours d'exécution - pas le fichier python en cours d'exécution. Imaginez que vous disposez d'un script qui, lorsqu'une erreur se produit, imprime le nom du script ainsi que les arguments autorisés. Vous mettez cela dans une fonction, en utilisant l'une de ces 2 techniques. À un moment donné, vous décidez de déplacer la fonction vers une bibliothèque externe. Souhaitez-vous imprimer le nom du script principal en cours d'exécution ou le nom du fichier de bibliothèque en cours d'exécution?
John Deighan

71

Dans un souci d'exhaustivité, j'ai pensé qu'il serait utile de résumer les différents résultats possibles et de fournir des références pour le comportement exact de chacun:

  • __file__est le fichier en cours d'exécution, comme détaillé dans la documentation officielle :

    __file__est le chemin d'accès du fichier à partir duquel le module a été chargé, s'il a été chargé à partir d'un fichier. L' __file__attribut peut être manquant pour certains types de modules, tels que les modules C qui sont liés statiquement à l'interpréteur; pour les modules d'extension chargés dynamiquement à partir d'une bibliothèque partagée, c'est le chemin d'accès du fichier de bibliothèque partagée.

    À partir de Python3.4 , par problème 18416 , __file__est toujours un chemin absolu, sauf si le fichier en cours d'exécution est un script qui a été exécuté directement (pas via l'interpréteur avec l' -moption de ligne de commande) en utilisant un chemin relatif.

  • __main__.__file__(nécessite l'importation __main__) accède simplement à l' __file__attribut susmentionné du module principal , par exemple du script qui a été appelé à partir de la ligne de commande.

  • sys.argv[0](nécessite l'importation sys) est le nom du script qui a été appelé à partir de la ligne de commande, et peut être un chemin absolu, comme détaillé dans la documentation officielle :

    argv[0]est le nom du script (il dépend du système d'exploitation, qu'il s'agisse ou non d'un chemin d'accès complet). Si la commande a été exécutée à l'aide de l' -coption de ligne de commande de l'interpréteur, argv[0]est définie sur la chaîne '-c'. Si aucun nom de script n'a été transmis à l'interpréteur Python, il argv[0]s'agit de la chaîne vide.

    Comme mentionné dans une autre réponse à cette question , les scripts Python qui ont été convertis en programmes exécutables autonomes via des outils tels que py2exe ou PyInstaller peuvent ne pas afficher le résultat souhaité lors de l'utilisation de cette approche (c'est sys.argv[0]-à- dire contenir le nom de l'exécutable plutôt que le nom du fichier Python principal dans cet exécutable).

  • Si aucune des options susmentionnées ne semble fonctionner, probablement en raison d'une opération d'importation irrégulière, le module d'inspection peut s'avérer utile. En particulier, invoquer inspect.getfile(...)sur inspect.currentframe()pourrait fonctionner, bien que ce dernier revienneNone lors de l'exécution dans une implémentation sans cadre de pile Python .


Gérer les liens symboliques

Si le script actuel est un lien symbolique, alors tout ce qui précède retournerait le chemin du lien symbolique plutôt que le chemin du fichier réel et os.path.realpath(...)devrait être invoqué pour extraire ce dernier.


Manipulations supplémentaires qui extraient le nom de fichier réel

os.path.basename(...)peut être invoqué sur l'un des éléments ci-dessus afin d'extraire le nom de fichier réel et os.path.splitext(...)peut être invoqué sur le nom de fichier réel afin de tronquer son suffixe, comme dans os.path.splitext(os.path.basename(...)).

À partir de Python 3.4 , conformément au PEP 428 , la PurePathclasse du pathlibmodule peut également être utilisée sur n'importe lequel des éléments ci-dessus. Plus précisément, pathlib.PurePath(...).nameextrait le nom de fichier réel et pathlib.PurePath(...).stemextrait le nom de fichier réel sans son suffixe.


66

Notez que __file__cela donnera le fichier où réside ce code, qui peut être importé et différent du fichier principal en cours d'interprétation. Pour obtenir le fichier principal, le module spécial __main__ peut être utilisé:

import __main__ as main
print(main.__file__)

Notez que cela __main__.__file__fonctionne dans Python 2.7 mais pas dans 3.2, utilisez donc la syntaxe import-as comme ci-dessus pour la rendre portable.


Cela fonctionne dans de nombreux cas, mais pas lorsque j'utilise le rPythonpackage à partir de la Rlangue. Ce doit être un cas exceptionnel qui est tout simplement trop difficile à gérer.
Leonid

En effet, le package rPython intègre l'interpréteur python, ce qui signifie qu'il n'y a pas de fichier `` principal '' comme il en existe lorsque python s'exécute de manière autonome (vous trouverez le même comportement à chaque fois que python est incorporé). Il importe en __main__interne, pour être utilisé pour passer des variables entre Ret python, il serait donc relativement facile de le définir __main__.__file__avant d'appeler autre chose, mais je ne suis même pas sûr de ce que serait une valeur appropriée dans ce cas.
Perkins

42

Les réponses ci-dessus sont bonnes. Mais j'ai trouvé cette méthode plus efficace en utilisant les résultats ci-dessus.
Il en résulte que le nom de fichier de script réel n'est pas un chemin.

import sys    
import os    
file_name =  os.path.basename(sys.argv[0])

1
J'aime aussi séparer l'extension, donc j'utilise: os.path.splitext (os.path.basename (sys.argv [0])) [0]
RufusVS

19

Pour les versions modernes de Python (3.4+), Path(__file__).namedevrait être plus idiomatique. Vous Path(__file__).stemdonne également le nom du script sans l' .pyextension.


NameError: le nom 'Path' n'est pas défini
RufusVS

5
Vous devriez d' from pathlib import Pathabord.
Emil Melnikov

"moderne" signifie Python 3.x?
einpoklum

1
@einpoklum a pathlibété introduit dans Python 3.4, il devrait donc fonctionner à partir de Python 3.4.
Andrey Semakin


9

Remarque: Si vous utilisez Python 3+, vous devez utiliser la fonction print () à la place

En supposant que le nom de fichier est foo.py, l'extrait ci-dessous

import sys
print sys.argv[0][:-3]

ou

import sys
print sys.argv[0][::-1][3:][::-1]

Comme pour les autres extensions avec plus de caractères, par exemple le nom de fichier foo.pypy

import sys
print sys.argv[0].split('.')[0]

Si vous souhaitez extraire d'un chemin absolu

import sys
print sys.argv[0].split('/')[-1].split('.')[0]

affichera foo


1
sys.argv [0] [: - 3] ferait l'affaire
kon psych

@konpsych c'est plus élégant
xtonousou

Il y a une grande différence entre __file__et sys.argv[0], voir stackoverflow.com/questions/5851588/…
Maksym Ganenko

8

Le premier argument dans sys sera le nom du fichier actuel, donc cela fonctionnera

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

7

Si vous effectuez une importation inhabituelle (par exemple, c'est un fichier d'options), essayez:

import inspect
print (inspect.getfile(inspect.currentframe()))

Notez que cela renverra le chemin absolu du fichier.


3

nous pouvons essayer ceci pour obtenir le nom du script actuel sans extension.

import os

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

2

Étant donné que l'OP a demandé le nom du fichier de script actuel, je préférerais

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

1

toutes ces réponses sont excellentes, mais ont quelques problèmes que vous pourriez ne pas voir au premier coup d'œil.

permet de définir ce que nous voulons - nous voulons le nom du script qui a été exécuté, pas le nom du module actuel - __file__ne fonctionnera donc que s'il est utilisé dans le script exécuté, pas dans un module importé. sys.argvest également discutable - et si votre programme était appelé par pytest? ou coureur pydoc? ou si elle a été appelée par uwsgi?

et - il y a une troisième méthode pour obtenir le nom du script, je n'ai pas vu dans les réponses - Vous pouvez inspecter la pile.

Un autre problème est que vous (ou un autre programme) pouvez altérer sys.argvet__main__.__file__ - il peut être présent, il se peut que ce ne soit pas le cas. Il peut être valide ou non. Vous pouvez au moins vérifier si le script (le résultat souhaité) existe!

ma bibliothèque bitranox / lib_programname sur github fait exactement cela:

  • vérifier s'il __main__est présent
  • vérifier s'il __main__.__file__est présent
  • donne __main__.__file__un résultat valide (ce script existe-t-il?)
  • sinon: vérifiez sys.argv:
  • y a-t-il pytest, docrunner, etc. dans le sys.argv? -> si oui, ignorez ça
  • pouvons-nous obtenir un résultat valide ici?
  • sinon: inspectez la pile et obtenez éventuellement le résultat
  • si la pile ne donne pas non plus de résultat valide, lancez une exception.

par là, ma solution fonctionne à ce jour avec setup.py test, uwsgi, pytest, pycharm pytest, pycharm docrunner (doctest), dreampie,eclipse

il y a aussi un bel article de blog sur ce problème de Dough Hellman, "Déterminer le nom d'un processus à partir de Python"


0

Ma solution rapide et sale:

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

2
Meilleure utilisation os.pathpour diviser les noms de fichiers
Maksym Ganenko


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.