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
SubniC
fonte

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

Sven Marnach
fonte
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.)

Chris Morgan
fonte
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.

Yoel
fonte
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.

Ambroz Bizjak
fonte
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])
Manoj Sahu
fonte
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.

Emil Melnikov
fonte
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

Tente o seguinte:

print __file__
demas
fonte
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

xtonousou
fonte
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
Charlie OConor
fonte
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.

Gajendra D Ambi
fonte
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]
Krishn Singh
fonte
2

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

import os
os.path.split(sys.argv[0])[1]
PeterXX
fonte
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"

bitranox
fonte
0

Minha solução rápida e suja:

__file__.split('/')[-1:][0]
E.Big
fonte
2
Melhor utilização os.pathde nomes de arquivos de divisão
Maksym Ganenko
0

No Python 3.5, você pode simplesmente fazer:

from pathlib import Path
Path(__file__).stem

Veja mais aqui: https://docs.python.org/3.5/library/pathlib.html#pathlib.PurePath.stem

Por exemplo, eu tenho um arquivo no meu diretório de usuário chamado test.pycom este dentro:

from pathlib import Path

print(Path(__file__).stem)
print(__file__)

executando estas saídas:

>>> python3.6 test.py
test
test.py
elad prata
fonte