Obter o nome do script atual em Python


408

Estou tentando obter o nome do script Python que está sendo executado no momento.

Eu tenho um script chamado foo.pye gostaria de fazer algo assim para obter o nome do script:

print Scriptname

Respostas:


621

Você pode usar __file__para obter o nome do arquivo atual. Quando usado no módulo principal, este é o nome do script que foi originalmente chamado.

Se você deseja omitir a parte do diretório (que pode estar presente), você pode usar os.path.basename(__file__).


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

20
@sdaau: __file__não está definido no intérprete interativo, porque não faz sentido lá. Ele é definido pela implementação de importação; portanto, se você usar um mecanismo de importação não padrão, ele também poderá ser desabilitado.
Sven Marnach

8
Pelo menos para o Python 2.7, acredito que import osseja necessário que isso funcione. Eu adicionaria isso na resposta.
Nick Chammas

14
@ cdunn2001: import ose import os.pathsão completamente equivalentes.
Sven Marnach

2
@ Sven-Marnach: Oh, você está certo . Eu venho fazendo errado há anos!
cdunn2001

136
import sys
print sys.argv[0]

Isso será impresso foo.pypara python foo.py, dir/foo.pypara python dir/foo.pyetc. É o primeiro argumento para python. (Observe que após o py2exe seria foo.exe.)


33
@ DenisMalinovsky: defina "não funcionará". Se você ligar python linkfile.py, onde linkfile.pyestá um link simbólico para realfile.py, sys.argv[0]será 'linkfile.py', que pode ou não ser o que você deseja; é certamente o que eu espero . __file__é o mesmo: será linkfile.py. Se você quiser encontrar 'realfile.py'a partir 'linkfile.py', tente os.path.realpath('linkfile.py').
13133 Chris Morgan

6
+1 porque é (a) um pouco mais organizado e (b) ainda funcionará no módulo (onde a variável file seria o arquivo do módulo, não o executado).
21915 Robert

Essa resposta é boa porque também funciona no IDLE. Como uma nota, para obter apenas o nome do arquivo, você pode escrever os.path.basename (sys.argv [0])
Steven Bluen

Mais importante, isso não funciona, exceto de dentro do arquivo principal. Não use isso, use em __file__vez disso.
Apollys suporta Monica

O QUE!!! Você tentou isso? Exatamente o oposto é verdadeiro. O interlocutor perguntou o nome do script python que está sendo executado - não o arquivo python que está em execução no momento. Imagine que você tenha um script que, quando ocorrer um erro, imprima o nome do script junto com os argumentos permitidos. Você coloca isso em uma função, usando uma dessas 2 técnicas. Em algum momento, você decide mover a função para uma biblioteca externa. Deseja imprimir o nome do script principal em execução ou o nome do arquivo da biblioteca que está sendo executado?
John Deighan 30/04

71

Por uma questão de integridade, pensei que valeria a pena resumir os vários resultados possíveis e fornecer referências para o comportamento exato de cada um:

  • __file__é o arquivo em execução no momento, conforme detalhado na documentação oficial :

    __file__é o nome do caminho do arquivo do qual o módulo foi carregado, se foi carregado de um arquivo. O __file__atributo pode estar ausente para certos tipos de módulos, como módulos C que estão estaticamente vinculados ao intérprete; para módulos de extensão carregados dinamicamente de uma biblioteca compartilhada, é o nome do caminho do arquivo da biblioteca compartilhada.

    A partir do Python3.4 em diante, pela edição 18416 , __file__sempre é um caminho absoluto, a menos que o arquivo em execução no momento seja um script que tenha sido executado diretamente (não através do interpretador com a -mopção de linha de comando) usando um caminho relativo.

  • __main__.__file__(requer importação __main__) simplesmente acessa o __file__atributo acima mencionado do módulo principal , por exemplo, do script que foi chamado a partir da linha de comando.

  • sys.argv[0](requer importação sys) é o nome do script que foi chamado a partir da linha de comando e pode ser um caminho absoluto, conforme detalhado na documentação oficial :

    argv[0]é o nome do script (depende do sistema operacional se este é um nome de caminho completo ou não). Se o comando foi executado usando a -copção de linha de comando para o intérprete, argv[0]é definido como a sequência '-c'. Se nenhum nome de script foi passado para o interpretador Python, argv[0]é a string vazia.

    Como mencionado em outra resposta a essa pergunta , os scripts Python que foram convertidos em programas executáveis ​​independentes por meio de ferramentas como py2exe ou PyInstaller podem não exibir o resultado desejado ao usar essa abordagem (ou seja sys.argv[0], manter o nome do executável em vez do nome do arquivo Python principal nesse executável).

  • Se nenhuma das opções mencionadas acima parecer funcionar, provavelmente devido a uma operação de importação irregular, o módulo de inspeção poderá ser útil. Em particular, a invocação inspect.getfile(...)de inspect.currentframe()poderia funcionar, embora o último retornasseNone ao executar em uma implementação sem o quadro de pilha Python .


Manipulando Links Simbólicos

Se o script atual for um link simbólico, todas as opções acima retornariam o caminho do link simbólico em vez do caminho do arquivo real e os.path.realpath(...)devem ser invocadas para extrair o último.


Manipulações adicionais que extraem o nome do arquivo real

os.path.basename(...)pode ser chamado em qualquer uma das opções acima para extrair o nome do arquivo real e os.path.splitext(...)pode ser chamado no nome do arquivo real para truncar seu sufixo, como em os.path.splitext(os.path.basename(...)).

A partir do Python 3.4 em diante, de acordo com o PEP 428 , a PurePathclasse do pathlibmódulo também pode ser usada em qualquer um dos itens acima. Especificamente, pathlib.PurePath(...).nameextrai o nome real do arquivo e pathlib.PurePath(...).stemextrai o nome real do arquivo sem seu sufixo.


66

Observe que __file__fornecerá o arquivo em que esse código reside, que pode ser importado e diferente do arquivo principal que está sendo interpretado. Para obter o arquivo principal, o módulo __main__ especial pode ser usado:

import __main__ as main
print(main.__file__)

Observe que __main__.__file__funciona no Python 2.7, mas não no 3.2, portanto, use a sintaxe de importação como acima para torná-lo portátil.


Isso funciona em muitos casos, mas não quando estou usando o rPythonpacote do Ridioma. Esse deve ser um caso excepcional e difícil de lidar.
Leonid

De fato, o pacote rPython incorpora o interpretador python, o que significa que não há um arquivo 'principal' como existe quando o python está rodando por conta própria (você encontrará o mesmo comportamento sempre que o python for incorporado). Ele é importado __main__internamente, para uso na passagem de variáveis ​​entre Re python, portanto, seria relativamente fácil configurá-lo __main__.__file__antes de chamar qualquer outra coisa, mas não tenho certeza do que seria um valor apropriado nesse caso.
Perkins

42

As respostas acima são boas. Mas achei esse método mais eficiente usando os resultados acima.
Isso resulta no nome do arquivo de script real, não em um caminho.

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

11
Eu gosto de separar a extensão também, então eu uso: os.path.splitext (os.path.basename (sys.argv [0])) [0]
RufusVS

19

Para versões modernas do Python (3.4+), Path(__file__).namedeve ser mais idiomático. Além disso, Path(__file__).stemfornece o nome do script sem a .pyextensão.


NameError: o nome 'Caminho' não está definido
RufusVS 23/07

5
Você deveria from pathlib import Pathprimeiro.
Emil Melnikov

"moderno" significa Python 3.x?
einpoklum 18/03

11
O @einpoklum pathlibfoi introduzido no Python 3.4, portanto deve funcionar a partir do Python 3.4.
Andrey Semakin


9

Nota: Se você estiver usando o Python 3+, use a função print ()

Supondo que o nome do arquivo seja foo.py, o trecho abaixo

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

ou

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

Quanto a outras extensões com mais caracteres, por exemplo, o nome do arquivo foo.pypy

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

Se você deseja extrair de um caminho absoluto

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

irá produzir foo


11
sys.argv [0] [: - 3] faria #
kon psych

@konpsych que é mais elegante
xtonousou

Há grande diferença entre __file__e sys.argv[0], ver stackoverflow.com/questions/5851588/...
Maksym Ganenko

8

O primeiro argumento em sys será o nome do arquivo atual, portanto, isso funcionará

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

7

Se você estiver fazendo uma importação incomum (por exemplo, é um arquivo de opções), tente:

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

Observe que isso retornará o caminho absoluto para o arquivo.


3

podemos tentar isso para obter o nome do script atual sem extensão.

import os

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

2

Como o OP solicitou o nome do arquivo de script atual, eu preferiria

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

1

todas essas respostas são ótimas, mas têm alguns problemas Você pode não ver à primeira vista.

vamos definir o que queremos - queremos o nome do script que foi executado, não o nome do módulo atual - portanto __file__, só funcionará se for usado no script executado, não em um módulo importado. sys.argvtambém é questionável - e se o seu programa foi chamado pelo pytest? ou corredor pydoc? ou se foi chamado por uwsgi?

e - existe um terceiro método para obter o nome do script, que eu não vi nas respostas - Você pode inspecionar a pilha.

Outro problema é que você (ou algum outro programa) pode mexer com sys.argve__main__.__file__ - pode estar presente, pode não estar. Pode ser válido ou não. Pelo menos Você pode verificar se o script (o resultado desejado) existe!

minha biblioteca bitranox / lib_programname no github faz exatamente isso:

  • verifique se __main__está presente
  • verifique se __main__.__file__está presente
  • fornece __main__.__file__um resultado válido (esse script existe?)
  • caso contrário, verifique sys.argv:
  • existe pytest, docrunner, etc no sys.argv? -> se sim, ignore isso
  • podemos obter um resultado válido aqui?
  • caso contrário: inspecione a pilha e obtenha o resultado daí, possivelmente
  • se também a pilha não der um resultado válido, lance uma exceção.

por esse caminho, a minha solução está trabalhando até agora com setup.py test, uwsgi, pytest, pycharm pytest, pycharm docrunner (doctest), dreampie,eclipse

também há um bom artigo de blog sobre esse problema de Dough Hellman, "Determinando o nome de um processo no Python"


0

Minha solução rápida e suja:

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

2
Melhor utilização os.pathde nomes de arquivos de divisão
Maksym Ganenko


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.