Pergunta

Tenho scripts que chamam outros arquivos de script, mas preciso obter o caminho do arquivo que está sendo executado no processo.

Por exemplo, digamos que eu tenha três arquivos.Usando arquivo executivo:

  • script_1.py chamadas script_2.py.
  • Por sua vez, script_2.py chamadas script_3.py.

Como posso obter o nome do arquivo e o caminho do script_3.py, do código dentro script_3.py, sem ter que passar essas informações como argumentos de script_2.py?

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

Foi útil?

Solução

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

Outras dicas

__file__

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

import os

os.path.realpath(__file__)

Atualização 28/11/2018:

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 Python 2, pode ser mais claro mudar para pacotes para poder usar from lib import bar - basta adicionar vazio __init__.py arquivos para as duas pastas.

Para Python 3, execfile não existe - a alternativa mais próxima é exec(open(<filename>).read()), embora isso afete os quadros de pilha.É mais simples apenas usar import foo e import lib.bar - não __init__.py arquivos necessários.

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


Resposta Original:

Aqui está um experimento baseado nas respostas deste tópico - com 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ão eles sendo adicionados a sistema como funções!Créditos para @Usagi e @pablog

Com base nos três arquivos a seguir e executando main.py de sua pasta com python main.py (também tentei execfiles com caminhos absolutos e chamadas 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

Eu acho que isso é mais limpo:

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

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

print inspect.getfile(inspect.currentframe())

Onde [0] é o quadro atual na pilha (topo da pilha) e [1] é para 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] levará você ao final da pilha, o script de chamada original.

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

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

Se você quiser descobrir o nome do executável (ou seja,o arquivo raiz passado para o interpretador python do programa atual) de um arquivo que pode ser importado como um módulo, você precisa 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).

Então no arquivo bar.py se você import foo vai imprimir bar.py, em vez de foo.py, que seria o valor de todos estes:

  • __file__
  • inspect.getfile(inspect.currentframe())
  • inspect.stack()[0][1]
import os
print os.path.basename(__file__)

isso nos dará apenas o nome do arquivo.ou sejase o abspath do arquivo for c:\abcd\abc.py então a 2ª linha imprimirá abc.py

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

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

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

Eu tenho um script que deve funcionar em 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 é o mais importante no meu caso.

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

Não há necessidade de inspeção 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 residente na mesma pasta do script importado.

O __file__ O atributo funciona tanto para o arquivo que contém o código de execução principal quanto para os módulos importados.

Ver https://web.archive.org/web/20090918095828/http://pyref.infogami.com/__file__

import sys

print sys.path[0]

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

Eu acho que é só __file__ Parece que você também pode querer verificar o inspecionar módulo.

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'

Tente isso,

import os
os.path.dirname(os.path.realpath(__file__))
import sys
print sys.argv[0]

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

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

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

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

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

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

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 seguintes execuções dão o nome do arquivo *.pyc
então fiquei com:
inspect.getfile(inspect.currentframe())
ou
sys._getframe().f_code.co_filename

Eu escrevi uma função que leva em conta o eclipse depurador e teste de unidade.Ele retorna a pasta do primeiro script que você inicia.Opcionalmente, você pode especificar o __arquivo__ var, mas o principal é que você não precisa compartilhar essa variável entre todos os seus hierarquia de chamada.

Talvez você consiga lidar com outras pilhas de casos específicos que 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_))

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]

P.S.:eu tentei execfile, mas como lê script_2.py como uma string, sys.argv[0] devolvida <string>.

Sempre usei apenas 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()

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

Portanto, esta resposta anterior de pontuação alta do usuário13993 em 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 em 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

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

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

file_name Imprimirá o TestScript, você pode gerar o que quiser, alterando o índice dentro [

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)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top