Como obtenho o caminho e o nome do arquivo que está sendo executado atualmente?


482

Tenho scripts chamando outros arquivos de script, mas preciso obter o caminho do arquivo atualmente em execução no processo.

Por exemplo, digamos que eu tenho três arquivos. Usando execfile :

  • script_1.pychamadas script_2.py.
  • Por sua vez, script_2.py chama script_3.py.

Como posso obter o nome do arquivo e o caminho de script_3.py, a partir do código dentroscript_3.py , sem ter que passar essa informação como argumentos a partir de script_2.py?

(Executando os.getcwd() retorna o caminho do arquivo do script inicial original e não o arquivo atual.)



2
os.path.realpath ( arquivo )
Girish Gupta

Respostas:


256

p1.py:

execfile("p2.py")

p2.py:

import inspect, os
print (inspect.getfile(inspect.currentframe()) # script filename (usually with path)
print (os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))) # script directory

11
CUIDADO: Esta chamada não fornece o mesmo resultado em ambientes diferentes. Considere aceitar a resposta de Usagi abaixo: stackoverflow.com/a/6628348/851398
faraday

3
@faraday: Você poderia dar um exemplo? Eu respondi a perguntas semelhantes usandoinspect.getabsfile() e funcionou para todos os casos que tentei.
JFS

1
De fato, a resposta do @Usagi é melhor?
Dror

4
nah user13993 acertou muito melhor
osirisgothra

6
user13993 realmente acertou em cheio. Deveria seros.path.realpath(__file__)
uchuugaka 13/08/2015

566
__file__

como outros já disseram. Você também pode usar o os.path.realpath para eliminar links simbólicos:

import os

os.path.realpath(__file__)

14
É preciso ter cuidado com essa abordagem, porque algumas vezes __file__retorna 'script_name.py' e outras vezes 'script_name.pyc'. Portanto, a saída não é estável.
Mechatroner

27
Mas como estamos usando apenas o caminho desse arquivo, isso é irrelevante.
Uwe Koloska

5
isso é estranho: ao executar a partir da linha de comando "__file__"entre aspas (como string), fornece o diretório a partir do qual o cmd é executado, mas __file__ (sem aspas indica o caminho para o arquivo de origem ... por que é isso?
muon

7
@muon não há verificação realizada se existe uma string de nome de arquivo transmitida, e como os caminhos do arquivo são relativos ao cwd, é isso que a os.path.realpathfunção supõe que seja a dirparte do caminho. os.path.dirname(os.path.realpath(__file__))retorna o diretório com o arquivo os.path.dirname(os.path.realpath("__file__"))retorna cwd. os.path.dirname(os.path.realpath("here_be_dragons"))também retorna cwd.
Jamie Touro

86

Atualização 2018-11-28:

Aqui está um resumo dos experimentos com Python 2 e 3. Com

main.py - executa foo.py
foo.py - executa lib / bar.py
lib / bar.py - imprime expressões de caminho de arquivo

| Python | Run statement       | Filepath expression                    |
|--------+---------------------+----------------------------------------|
|      2 | execfile            | os.path.abspath(inspect.stack()[0][1]) |
|      2 | from lib import bar | __file__                               |
|      3 | exec                | (wasn't able to obtain it)             |
|      3 | import lib.bar      | __file__                               |

Para o Python 2, pode ser mais claro alternar para pacotes para que possa ser usado from lib import bar- basta adicionar__init__.py arquivos às duas pastas.

Para o Python 3, execfilenão existe - a alternativa mais próxima é exec(open(<filename>).read()), embora isso afete os quadros da pilha. É mais simples de usar import fooe import lib.bar- não é __init__.pynecessário arquivo.

Veja também Diferença entre importação e execfile


Resposta original:

Aqui está um experimento baseado nas respostas neste tópico - com o Python 2.7.10 no Windows.

Os baseados em pilha são os únicos que parecem fornecer resultados confiáveis. Os dois últimos têm a sintaxe mais curta , ou seja -

print os.path.abspath(inspect.stack()[0][1])                   # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1]))  # C:\filepaths\lib

Aqui está a estes sendo adicionados ao sys como funções! Crédito para @Usagi e @pablog

Com base nos três arquivos a seguir, e executando o main.py a partir de sua pasta com python main.py(também tentou execfiles com caminhos absolutos e chamando de uma pasta separada).

C: \ filepaths \ main.py: execfile('foo.py')
C: \ filepaths \ foo.py: execfile('lib/bar.py')
C: \ filepaths \ lib \ bar.py:

import sys
import os
import inspect

print "Python " + sys.version
print

print __file__                                        # main.py
print sys.argv[0]                                     # main.py
print inspect.stack()[0][1]                           # lib/bar.py
print sys.path[0]                                     # C:\filepaths
print

print os.path.realpath(__file__)                      # C:\filepaths\main.py
print os.path.abspath(__file__)                       # C:\filepaths\main.py
print os.path.basename(__file__)                      # main.py
print os.path.basename(os.path.realpath(sys.argv[0])) # main.py
print

print sys.path[0]                                     # C:\filepaths
print os.path.abspath(os.path.split(sys.argv[0])[0])  # C:\filepaths
print os.path.dirname(os.path.abspath(__file__))      # C:\filepaths
print os.path.dirname(os.path.realpath(sys.argv[0]))  # C:\filepaths
print os.path.dirname(__file__)                       # (empty string)
print

print inspect.getfile(inspect.currentframe())         # lib/bar.py

print os.path.abspath(inspect.getfile(inspect.currentframe())) # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # C:\filepaths\lib
print

print os.path.abspath(inspect.stack()[0][1])          # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1]))  # C:\filepaths\lib
print

72

Eu acho que isso é mais limpo:

import inspect
print inspect.stack()[0][1]

e obtém as mesmas informações de:

print inspect.getfile(inspect.currentframe())

Onde [0] é o quadro atual na pilha (parte superior da pilha) e [1] é o nome do arquivo, aumente para retroceder na pilha, ou seja,

print inspect.stack()[1][1]

seria o nome do arquivo do script que chamou o quadro atual. Além disso, usar [-1] o levará ao final da pilha, o script de chamada original.


4
Não recomende confiar na posição dentro da tupla. Não está claro quais dados você está tentando obter ao ler o código.
Jpmc26

5
inspect.getfile()retorna o __file__atributo se passou um objeto de módulo. inspect.currentframe()retorna o módulo. Portanto, essa é uma maneira cara de dizer __file__.
Martijn Pieters

inspect.stack()é uma função bastante cara, mais do que justa inspect.currentframe(), e também chama inspect.getfile()um objeto de módulo.
Martijn Pieters

42
import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only

1
Acabei de experimentar o comentário de @Pat Notz. Eu acho que você pode simplesmente obter o nome do arquivo __file__.
precisa saber é o seguinte

No Python3, os.path.dirnamevocê fornecerá o caminho relativo de onde você está executando o script. por exemplo, python ../../test.pyo os.path.dirnameserá ../../, e não o caminho absoluto para o script. Eu estava procurando abspath, mas removendo o nome do script. O primeiro elemento do sys.path aparentemente é a resposta sys.path[0].
aerijman

37

As sugestões marcadas como melhores serão verdadeiras se o seu script consistir em apenas um arquivo.

Se você deseja descobrir o nome do executável (ou seja, o arquivo raiz passado ao intérprete python para o programa atual) de um arquivo que pode ser importado como um módulo, é necessário fazer isso (vamos supor que isso esteja em um arquivo chamado foo.py ):

import inspect

print inspect.stack()[-1][1]

Porque a última coisa ( [-1]) na pilha é a primeira coisa que entra nela (pilhas são estruturas de dados LIFO / FILO).

Em seguida, no arquivo bar.py, se você import fooimprimir bar.py , em vez de foo.py , que seria o valor de todos eles:

  • __file__
  • inspect.getfile(inspect.currentframe())
  • inspect.stack()[0][1]

Ele funciona bem, mas não para teste de unidade em eclipse, eu tenho /home/user/Softwares/eclipse/plugins/org.python.pydev_4.5.5.201603221110/pysrc
hayj

2
Esta é uma maneira cara de ortografia sys.modules['__main__'].__file__, na verdade.
Martijn Pieters

14
import os
print os.path.basename(__file__)

isso nos dará apenas o nome do arquivo. ou seja, se abspath do arquivo for c: \ abcd \ abc.py, a segunda linha imprimirá abc.py


14

Não está totalmente claro o que você quer dizer com "o caminho do arquivo que está em execução no processo". sys.argv[0]geralmente contém a localização do script que foi chamado pelo intérprete Python. Verifique a documentação do sistema para mais detalhes.

Como o @Tim e o @Pat Notz apontaram, o atributo __file__ fornece acesso a

o arquivo do qual o módulo foi carregado, se foi carregado de um arquivo


1
"print os.path.abspath ( file )" e "print inspect.getfile (inspect.currentframe ())" não funciona quando passamos o programa python para um exe do win32. Somente sys.argv [0] funciona! :) mas você só pega o nome!
aF.

11

Eu tenho um script que deve funcionar no ambiente Windows. Este código cortado é o que eu terminei:

import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0])

é uma decisão bastante hacky. Mas não requer bibliotecas externas e é a coisa mais importante no meu caso.


1
Eu tive que "importar os, sys" para isso, mas até agora é a melhor resposta que realmente retorna apenas o caminho sem um nome de arquivo no final da string.
Emmagras 18/10/2014

10

Tente isso,

import os
os.path.dirname(os.path.realpath(__file__))

8
import os
os.path.dirname(os.path.abspath(__file__))

Não há necessidade de inspecionar ou qualquer outra biblioteca.

Isso funcionou para mim quando tive que importar um script (de um diretório diferente do script executado), que usava um arquivo de configuração que residia na mesma pasta que o script importado.


Isso não produzirá a resposta desejada se o diretório de trabalho atual (os.getcwd) for diferente do diretório em que o arquivo está localizado.
Ferro Pillow

2
Como assim? Funciona bem para mim neste caso. Eu obter o diretório do arquivo está localizado no.
Michael Mior

@IronPillow, talvez esta resposta o ajude com o que você precisa. stackoverflow.com/a/41546830/3123191
Kwuite


6
import sys

print sys.path[0]

isso imprimiria o caminho do script atualmente em execução


2
sys.path [0] é muito útil, mas dá o caminho da script1, não Script3 conforme solicitado
James

Pelo menos no OS X, com 2.7, não acho que isso seja confiável. Funciona se estiver executando diretamente o mesmo arquivo. Não funciona de repl, especialmente a partir de um ovo importado
uchuugaka


4

Você pode usar inspect.stack()

import inspect,os
inspect.stack()[0]  => (<frame object at 0x00AC2AC0>, 'g:\\Python\\Test\\_GetCurrentProgram.py', 15, '<module>', ['print inspect.stack()[0]\n'], 0)
os.path.abspath (inspect.stack()[0][1]) => 'g:\\Python\\Test\\_GetCurrentProgram.py'

4

Como o Python 3 é bastante popular, eu queria incluir uma pathlibresposta, pois acredito que agora é provavelmente uma ferramenta melhor para acessar informações de arquivos e caminhos.

from pathlib import Path

current_file: Path = Path(__file__).resolve()

Se você está procurando o diretório do arquivo atual, é tão fácil quanto adicionar .parentà Path()instrução:

current_path: Path = Path(__file__).parent.resolve()

3
import sys
print sys.argv[0]

10
Infelizmente, isso só funciona se o script foi chamado com o caminho completo, porque retorna apenas o "primeiro argumento" na linha de comando, que é a chamada para o script.
Cregox 13/05/10

2

Isso deve funcionar:

import os,sys
filename=os.path.basename(os.path.realpath(sys.argv[0]))
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))

2
print(__file__)
print(__import__("pathlib").Path(__file__).parent)

4
As respostas somente de código são desencorajadas. Por favor, adicione algumas explicações sobre como isso resolve o problema ou como isso difere das respostas existentes. Da avaliação
Nick

1

Para obter o diretório do script em execução

 print os.path.dirname( inspect.getfile(inspect.currentframe()))

1

Eu sempre usei o recurso OS do Current Working Directory, ou CWD. Isso faz parte da biblioteca padrão e é muito fácil de implementar. Aqui está um exemplo:

    import os
    base_directory = os.getcwd()

1
Você pode modificar sua resposta para que ela se aplique à pergunta feita? Esta resposta não se aplica à pergunta "Como obtenho o caminho e o nome do arquivo que está sendo executado no momento? "
Marco

1
Isso fornece o caminho de onde você executou o comando python. Portanto, parece funcionar quando você executa o python script.pycomando na mesma pasta que você já é, quando na realidade é o mesmo que executar pwdno linux.
George

0

Eu usei a abordagem com __file__,
os.path.abspath(__file__)
mas há um pequeno truque, ele retorna o arquivo .py quando o código é executado pela primeira vez, as próximas execuções dão o nome do arquivo * .pyc,
então fiquei com:
inspect.getfile(inspect.currentframe())
ou
sys._getframe().f_code.co_filename


0

Eu escrevi uma função que leva em conta o depurador do eclipse e o mais unittest . Ele retorna a pasta do primeiro script que você inicia. Opcionalmente, você pode especificar o __file__ var, mas o principal é que você não precisa compartilhar essa variável em toda a sua hierarquia de chamadas .

Talvez você possa lidar com outros casos específicos da pilha que eu não vi, mas para mim está tudo bem.

import inspect, os
def getRootDirectory(_file_=None):
    """
    Get the directory of the root execution file
    Can help: http://stackoverflow.com/questions/50499/how-do-i-get-the-path-and-name-of-the-file-that-is-currently-executing
    For eclipse user with unittest or debugger, the function search for the correct folder in the stack
    You can pass __file__ (with 4 underscores) if you want the caller directory
    """
    # If we don't have the __file__ :
    if _file_ is None:
        # We get the last :
        rootFile = inspect.stack()[-1][1]
        folder = os.path.abspath(rootFile)
        # If we use unittest :
        if ("/pysrc" in folder) & ("org.python.pydev" in folder):
            previous = None
            # We search from left to right the case.py :
            for el in inspect.stack():
                currentFile = os.path.abspath(el[1])
                if ("unittest/case.py" in currentFile) | ("org.python.pydev" in currentFile):
                    break
                previous = currentFile
            folder = previous
        # We return the folder :
        return os.path.dirname(folder)
    else:
        # We return the folder according to specified __file__ :
        return os.path.dirname(os.path.realpath(_file_))

0

Para manter a consistência da migração entre plataformas (macOS / Windows / Linux), tente:

path = r'%s' % os.getcwd().replace('\\','/')


2
Isto está errado. Isso fornece o caminho atual, mas não o caminho do arquivo atual.
Charles Plager 10/10

0

A maneira mais simples é:

em script_1.py:

import subprocess
subprocess.call(['python3',<path_to_script_2.py>])

em script_2.py:

sys.argv[0]

PS: Eu tentei execfile, mas como ele lê script_2.py como uma string, sys.argv[0]retornou <string>.


0

Aqui está o que eu uso para que eu possa lançar meu código em qualquer lugar sem problemas. __name__está sempre definido, mas __file__só é definido quando o código é executado como um arquivo (por exemplo, não no IDLE / iPython).

    if '__file__' in globals():
        self_name = globals()['__file__']
    elif '__file__' in locals():
        self_name = locals()['__file__']
    else:
        self_name = __name__

Como alternativa, isso pode ser escrito como:

self_name = globals().get('__file__', locals().get('__file__', __name__))

-2

A maioria dessas respostas foi escrita no Python versão 2.x ou anterior. No Python 3.x, a sintaxe da função print foi alterada para exigir parênteses, ou seja, print ().

Portanto, essa resposta mais alta do usuário13993 no Python 2.x:

import inspect, os
print inspect.getfile(inspect.currentframe()) # script filename (usually with path)
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # script directory

Torna-se no Python 3.x:

import inspect, os
print(inspect.getfile(inspect.currentframe())) # script filename (usually with path)
print(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) ) # script directory

-3

se você quiser apenas o nome do arquivo sem ./ou .pyvocê pode tentar isso

filename = testscript.py
file_name = __file__[2:-3]

file_name imprimirá o test-script, você poderá gerar o que quiser, alterando o índice dentro de []


-3
import os

import wx


# return the full path of this file
print(os.getcwd())

icon = wx.Icon(os.getcwd() + '/img/image.png', wx.BITMAP_TYPE_PNG, 16, 16)

# put the icon on the frame
self.SetIcon(icon)

7
os.getcwd () retorna o diretório WORKING atual do PROCESS, não o diretório do arquivo em execução no momento. Isso pode parecer retornar os resultados corretos, mas há muitos casos em que o resultado não seria o diretório pai do arquivo atual. Muito melhor usar os.path.dirname ( arquivo ) como sugerido acima.
Samaspin # 22/15
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.