Se você ainda está procurando neste site, atualize a resposta correta para isso . É muito mais limpo que a solução proposta e também funciona nos casos em que __file__não está definido.
Erikbwork
3
@ erikb85: não é apenas mais limpo; inspectA solução baseada em dados também funciona para execfile()maiúsculas e minúsculas quando __file__produz um nome errado silenciosamente.
isso responde como obter o caminho do módulo que você importa, mas não o módulo / script em que você está (para o script que você está executando, __file__não é um caminho completo, é relativo). Para o arquivo em que estou, tive que importar outro módulo do mesmo diretório e fazer como mostrado aqui. Alguém conhece uma maneira mais conveniente?
Ben Bryant
5
@hbdgaf certeza que não existe tal coisa como um built-inself.__file__
Dan Passaro
26
@BenBryant @hbdgaf os.path.dirname(__file__)funciona bem para mim e retorna o caminho abs do diretório do módulo.
Niccolò
9
Eu tentei fazer isso e recebi o traceback: AttributeError: 'module' object has no attribute '__file__'
Dorian Dore
5
@DorianDore Eu estava mexendo um pouco com os módulos e cheguei a uma solução path = module.__path__.__dict__["_path"][0], mas não tenho certeza se é portátil ou se não difere entre as versões do python. Ele está trabalhando para mim, ao contrário esta resposta que me dá o mesmo erro e inspectaumentos resposta TypeError: <module 'module' (namespace)> is a built-in module...
O módulo inspecionar fornece várias funções úteis para ajudar a obter informações sobre objetos ativos, como módulos, classes, métodos, funções, rastreamentos, objetos de quadro e objetos de código. Por exemplo, ele pode ajudá-lo a examinar o conteúdo de uma classe, recuperar o código fonte de um método, extrair e formatar a lista de argumentos de uma função ou obter todas as informações necessárias para exibir um rastreamento detalhado.
Exemplo:
>>>import os
>>>import inspect
>>> inspect.getfile(os)'/usr/lib64/python2.7/os.pyc'>>> inspect.getfile(inspect)'/usr/lib64/python2.7/inspect.pyc'>>> os.path.dirname(inspect.getfile(inspect))'/usr/lib64/python2.7'
Pesquisei essa pergunta várias vezes no Google e esta é a resposta mais razoável que já vi! Atualize as informações sobreinspect.currentframe()
erikbwork
a inspect.getfile()abordagem não funciona com o módulo _io, mas funciona com o módulo io.
Smdikipedia
70
Como as outras respostas disseram, a melhor maneira de fazer isso é com __file__(demonstrado novamente abaixo). No entanto, existe uma ressalva importante, que __file__NÃO existe se você estiver executando o módulo por conta própria (por exemplo, como __main__).
Por exemplo, digamos que você tenha dois arquivos (ambos no PYTHONPATH):
#/path1/foo.pyimport bar
print(bar.__file__)
e
#/path2/bar.pyimport os
print(os.getcwd())print(__file__)
Executar foo.py fornecerá a saída:
/path1 # "import bar" causes the line "print(os.getcwd())" to run/path2/bar.py # then "print(__file__)" runs/path2/bar.py # then the import statement finishes and "print(bar.__file__)" runs
No entanto, se você tentar executar o bar.py por conta própria, obterá:
/path2 # "print(os.getcwd())" still works fineTraceback(most recent call last):# but __file__ doesn't exist if bar.py is running as mainFile"/path2/bar.py", line 3,in<module>print(__file__)NameError: name '__file__'isnot defined
Espero que isto ajude. Essa advertência me custou muito tempo e confusão ao testar as outras soluções apresentadas.
Nesse caso, você pode usar sys.argv [0] no lugar do arquivo .
21713 Jimothy
4
Isso é uma advertência específica da versão? Nas versões 2.6 e 2.7, eu confio no arquivo , que funciona quando o nome __ == '__ main '. O único caso de falha que eu vi foi com "python -c 'print file '". Acrescentarei que algumas vezes o arquivo pode ser '<stdin>', o que acontece quando IDEs como o emacs executam o buffer atual.
Paul Du Bois
1
Note-se que levando-e-fuga "__" caracteres colocar uma palavra em negrito, de modo manter isso em mente ao ler os comentários anteriores :-P
Paul Du Bois
1
@PaulDuBois Você pode cercá-lo com tiques traseiros: ` __file__` torna__file__
fncomp
1
Como você consegue o NameError? @ Paul Du Bois: Eu tentei Python 2,3-3,4 e __file__é definida no entanto eu executar o arquivo Python: python a.py, python -ma, ./a.py.
JFS
43
Vou tentar abordar algumas variações dessa questão também:
localizando o caminho do script chamado
localizando o caminho do script atualmente em execução
localizando o diretório do script chamado
(Algumas dessas perguntas foram feitas no SO, mas foram fechadas como duplicatas e redirecionadas aqui.)
Advertências de uso __file__
Para um módulo que você importou:
import something
something.__file__
retornará o caminho absoluto do módulo. No entanto, dado o seguinte script foo.py:
#foo.pyprint'__file__', __file__
Chamando-o com 'python foo.py' Retornará simplesmente 'foo.py'. Se você adicionar um shebang:
e chame-o usando ./foo.py, ele retornará './foo.py'. Chamando-o de um diretório diferente (por exemplo, coloque foo.py na barra de diretórios) e, em seguida, chamando
python bar/foo.py
ou adicionando um shebang e executando o arquivo diretamente:
bar/foo.py
retornará 'bar / foo.py' (o parente caminho ).
Localizando o diretório
Agora, a partir daí, para obter o diretório, os.path.dirname(__file__)também pode ser complicado. Pelo menos no meu sistema, ele retornará uma string vazia se você a chamar do mesmo diretório que o arquivo. ex.
# foo.pyimport os
print'__file__ is:', __file__
print'os.path.dirname(__file__) is:', os.path.dirname(__file__)
irá produzir:
__file__ is: foo.py
os.path.dirname(__file__)is:
Em outras palavras, ele retorna uma cadeia vazia, portanto, isso não parece confiável se você deseja usá-la para o arquivo atual (ao contrário do arquivo de um módulo importado). Para contornar isso, você pode envolvê-lo em uma chamada para abspath:
# foo.pyimport os
print'os.path.abspath(__file__) is:', os.path.abspath(__file__)print'os.path.dirname(os.path.abspath(__file__)) is:', os.path.dirname(os.path.abspath(__file__))
Observe que abspath () NÃO resolve links simbólicos. Se você quiser fazer isso, use realpath (). Por exemplo, criando um link simbólico file_import_testing_link apontando para file_import_testing.py, com o seguinte conteúdo:
import os
print'abspath(__file__)',os.path.abspath(__file__)print'realpath(__file__)',os.path.realpath(__file__)
inspect.getfile (os) é o mesmo que os .__ file__ do código: def getfile (object): "" "Calcule em qual arquivo de origem ou compilado um objeto foi definido." "" if ismodule (object): if hasattr (objeto, ' arquivo '): retornar objeto .__ arquivo___
idanzalz
4
Você pode usar inspect.getfile(inspect.currentframe())para obter o caminho do script em execução no momento.
jbochi
33
Não entendo por que ninguém está falando sobre isso, mas para mim a solução mais simples é usar imp.find_module ("modulename") (documentação aqui ):
import imp
imp.find_module("os")
Ele fornece uma tupla com o caminho na segunda posição:
(<open file '/usr/lib/python2.7/os.py', mode 'U' at 0x7f44528d7540>,'/usr/lib/python2.7/os.py',('.py','U',1))
A vantagem desse método sobre o "inspecionar" é que você não precisa importar o módulo para fazê-lo funcionar e pode usar uma string na entrada. Útil ao verificar os módulos chamados em outro script, por exemplo.
EDIT :
No python3, o importlibmódulo deve fazer:
Doc de importlib.util.find_spec:
Retorne a especificação para o módulo especificado.
Primeiro, o sys.modules é verificado para ver se o módulo já foi importado. Se sim, então sys.modules [nome]. especificação é retornada. Se isso for definido como Nenhum, ValueError será gerado. Se o módulo não estiver no sys.modules, o sys.meta_path será procurado por uma especificação adequada com o valor de 'path' fornecido aos localizadores. Nenhum será retornado se nenhuma especificação puder ser encontrada.
Se o nome for para o submódulo (contém um ponto), o módulo pai é importado automaticamente.
Os argumentos de nome e pacote funcionam da mesma maneira que importlib.import_module (). Em outras palavras, nomes de módulos relativos (com pontos à esquerda) funcionam.
imp NÃO é depreciado no python 2 (versão atual 2.7.13). imp é depreciado no python 3 desde 3.4. importlib deve ser usado no python 3. Eu gosto desta solução, porque ele funciona até mesmo quando a importação real irá falhar (por exemplo, porque módulo de 64 bits para um motor de 32 bits)
mdew
E REALMENTE bom ao tentar encontrar o caminho do sqlite3 de 64 bits e a importação falhar. Perfeito.
rahvin_t
2
importlib.machinery.PathFinder().find_module("os").get_filename()Alternativa mais imp.find_modulecurta que eu encontrei no Python3 +. Se alguém está procurando o uso de importlib.util.find_spec.
Torxed 24/03/19
Esse método funciona sem importar o módulo real, o que é ótimo, pois estou usando isso para descobrir qual versão de um módulo está sendo importada de um computador compartilhado.
Gouda
19
Isso foi trivial.
Cada módulo possui uma __file__variável que mostra seu caminho relativo de onde você está agora.
Portanto, obter um diretório para o módulo notificá-lo é simples como:
Quase, mas não completamente, o arquivo não é "relativo a onde você está agora"; quando é relativo (que será apenas quando houver caminhos relativos no sys.path), é relativo ao local onde você estava quando o módulo foi carregado .
Charles Duffy
17
import os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)
não funciona no meu Linux python 2.6, uma vez que __file__é apenas dir / test.py, o abspath envolve o cwd para concluir o nome do caminho que não é o resultado desejado, mas se você importar um módulo, m.__file__obtém o resultado desejado.
Ben Bryant
10
import module
print module.__path__
Pacotes suportam mais um atributo especial __path__,. Isso é inicializado para ser uma lista que contém o nome do diretório que contém o pacote __init__.pyantes que o código nesse arquivo seja executado. Esta variável pode ser modificada; isso afeta futuras pesquisas por módulos e subpacotes contidos no pacote.
Embora esse recurso não seja frequentemente necessário, ele pode ser usado para estender o conjunto de módulos encontrados em um pacote.
Por isso, passei bastante tempo tentando fazer isso com o py2exe. O problema era obter a pasta base do script, se ele estava sendo executado como um script python ou como um executável py2exe. Também para que funcione se estava sendo executado a partir da pasta atual, de outra pasta ou (essa foi a mais difícil) do caminho do sistema.
Eventualmente, usei essa abordagem, usando sys.frozen como um indicador de execução no py2exe:
import os,sys
if hasattr(sys,'frozen'):# only when running in py2exe this exists
base = sys.prefix
else:# otherwise this is a regular python script
base = os.path.dirname(os.path.realpath(__file__))
Se a única ressalva de uso __file__for atual, o diretório relativo estiver em branco (ou seja, ao executar como um script a partir do mesmo diretório em que o script está), uma solução trivial será:
import os.path
mydir = os.path.dirname(__file__)or'.'
full = os.path.abspath(mydir)print __file__, mydir, full
E o resultado:
$ python teste.py
teste.py ./home/user/work/teste
O truque está or '.'após a dirname()ligação. Ele define o diretório como ., o que significa diretório atual e é um diretório válido para qualquer função relacionada ao caminho.
Assim, o uso abspath()não é realmente necessário. Mas se você o usar de qualquer maneira, o truque não será necessário: abspath()aceita caminhos em branco e o interpreta adequadamente como o diretório atual.
É melhor trocar a ordem e usar apenas os.path.dirname(os.path.abspath(__file__))porque, assim, você não precisa se preocupar com caminhos relativos. Uma oportunidade a menos para erros.
szali
3
Eu gostaria de contribuir com um cenário comum (no Python 3) e explorar algumas abordagens para ele.
A função interna open () aceita o caminho relativo ou absoluto como seu primeiro argumento. O caminho relativo é tratado como relativo ao diretório de trabalho atual, portanto, é recomendável passar o caminho absoluto para o arquivo.
Basta dizer, se você executar um arquivo de script com o seguinte código, é não garantiu que o example.txtarquivo será criado no mesmo diretório onde o arquivo de script está localizado:
with open('example.txt','w'):pass
Para corrigir esse código, precisamos obter o caminho para o script e torná-lo absoluto. Para garantir que o caminho seja absoluto, simplesmente usamos a função os.path.realpath () . Para obter o caminho para o script, existem várias funções comuns que retornam vários resultados do caminho:
os.getcwd()
os.path.realpath('example.txt')
sys.argv[0]
__file__
Ambas as funções os.getcwd () e os.path.realpath () retornam resultados do caminho com base no diretório de trabalho atual . Geralmente não é o que queremos. O primeiro elemento da lista sys.argv é o caminho do script raiz (o script que você executa), independentemente de você chamar a lista no próprio script raiz ou em qualquer um de seus módulos. Pode ser útil em algumas situações. A variável __file__ contém o caminho do módulo do qual foi chamado.
O código a seguir cria corretamente um arquivo example.txtno mesmo diretório em que o script está localizado:
Então, acima, eu tive que chamar maincli.py do módulo my_lib_a.py, sabendo que top_package e maincli.py estão no mesmo diretório. Aqui está como eu obtenho o caminho para maincli.py:
import sys
import os
import imp
classConfigurationException(Exception):pass# inside of my_lib_a.pydef get_maincli_path():
maincli_path = os.path.abspath(imp.find_module('maincli')[1])# top_package = __package__.split('.')[0]# mod = sys.modules.get(top_package)# modfile = mod.__file__# pkg_in_dir = os.path.dirname(os.path.dirname(os.path.abspath(modfile)))# maincli_path = os.path.join(pkg_in_dir, 'maincli.py')ifnot os.path.exists(maincli_path):
err_msg ='This script expects that "maincli.py" be installed to the '\
'same directory: "{0}"'.format(maincli_path)raiseConfigurationException(err_msg)return maincli_path
Com base na postagem de PlasmaBinturong, modifiquei o código.
Se você deseja fazer isso dinamicamente em um "programa", tente este código:
Meu argumento é que você talvez não saiba o nome exato do módulo para "codificá-lo". Pode ser selecionado em uma lista ou não estar em execução no momento para usar __file__.
(Eu sei, não vai funcionar no Python 3)
global modpath
modname ='os'#This can be any module name on the fly#Create a file called "modname.py"
f=open("modname.py","w")
f.write("import "+modname+"\n")
f.write("modpath = "+modname+"\n")
f.close()#Call the file with execfile()
execfile('modname.py')print modpath
<module 'os'from'C:\Python27\lib\os.pyc'>
Tentei me livrar do problema "global", mas encontrei casos em que não funcionava. Acho que "execfile ()" pode ser emulado no Python 3 Como esse é um programa, ele pode ser facilmente colocado em um método ou módulo para reuso.
Aqui está um script bash rápido, caso seja útil para qualquer pessoa. Eu só quero poder definir uma variável de ambiente para que eu possa pushdo código.
#!/bin/bash
module=${1:?"I need a module name"}
python << EOI
import $module
import os
print os.path.dirname($module.__file__)
EOI
__file__
não está definido.inspect
A solução baseada em dados também funciona paraexecfile()
maiúsculas e minúsculas quando__file__
produz um nome errado silenciosamente.import pathlib, module; pathlib.Path(module.__file__).resolve().parent
Isso éRespostas:
Na verdade, você fornecerá o caminho para o arquivo .pyc que foi carregado, pelo menos no Mac OS X. Então, acho que você pode:
Você também pode tentar:
Para obter o diretório do módulo.
fonte
__file__
não é um caminho completo, é relativo). Para o arquivo em que estou, tive que importar outro módulo do mesmo diretório e fazer como mostrado aqui. Alguém conhece uma maneira mais conveniente?self.__file__
os.path.dirname(__file__)
funciona bem para mim e retorna o caminho abs do diretório do módulo.AttributeError: 'module' object has no attribute '__file__'
path = module.__path__.__dict__["_path"][0]
, mas não tenho certeza se é portátil ou se não difere entre as versões do python. Ele está trabalhando para mim, ao contrário esta resposta que me dá o mesmo erro einspect
aumentos respostaTypeError: <module 'module' (namespace)> is a built-in module
...Há
inspect
módulo em python.Documentação oficial
Exemplo:
fonte
inspect
para obter o nome do arquivo atual; veja stackoverflow.com/a/50905/320036inspect.currentframe()
inspect.getfile()
abordagem não funciona com o módulo_io
, mas funciona com o móduloio
.Como as outras respostas disseram, a melhor maneira de fazer isso é com
__file__
(demonstrado novamente abaixo). No entanto, existe uma ressalva importante, que__file__
NÃO existe se você estiver executando o módulo por conta própria (por exemplo, como__main__
).Por exemplo, digamos que você tenha dois arquivos (ambos no PYTHONPATH):
e
Executar foo.py fornecerá a saída:
No entanto, se você tentar executar o bar.py por conta própria, obterá:
Espero que isto ajude. Essa advertência me custou muito tempo e confusão ao testar as outras soluções apresentadas.
fonte
__file__
` torna__file__
NameError
? @ Paul Du Bois: Eu tentei Python 2,3-3,4 e__file__
é definida no entanto eu executar o arquivo Python:python a.py
,python -ma
,./a.py
.Vou tentar abordar algumas variações dessa questão também:
(Algumas dessas perguntas foram feitas no SO, mas foram fechadas como duplicatas e redirecionadas aqui.)
Advertências de uso
__file__
Para um módulo que você importou:
retornará o caminho absoluto do módulo. No entanto, dado o seguinte script foo.py:
Chamando-o com 'python foo.py' Retornará simplesmente 'foo.py'. Se você adicionar um shebang:
e chame-o usando ./foo.py, ele retornará './foo.py'. Chamando-o de um diretório diferente (por exemplo, coloque foo.py na barra de diretórios) e, em seguida, chamando
ou adicionando um shebang e executando o arquivo diretamente:
retornará 'bar / foo.py' (o parente caminho ).
Localizando o diretório
Agora, a partir daí, para obter o diretório,
os.path.dirname(__file__)
também pode ser complicado. Pelo menos no meu sistema, ele retornará uma string vazia se você a chamar do mesmo diretório que o arquivo. ex.irá produzir:
Em outras palavras, ele retorna uma cadeia vazia, portanto, isso não parece confiável se você deseja usá-la para o arquivo atual (ao contrário do arquivo de um módulo importado). Para contornar isso, você pode envolvê-lo em uma chamada para abspath:
que gera algo como:
Observe que abspath () NÃO resolve links simbólicos. Se você quiser fazer isso, use realpath (). Por exemplo, criando um link simbólico file_import_testing_link apontando para file_import_testing.py, com o seguinte conteúdo:
A execução imprimirá caminhos absolutos, como:
file_import_testing_link -> file_import_testing.py
Usando inspecionar
O @SummerBreeze menciona o uso do módulo inspecionar .
Isso parece funcionar bem e é bastante conciso para os módulos importados:
obedientemente retorna o caminho absoluto. No entanto, para encontrar o caminho do script em execução no momento, não vi uma maneira de usá-lo.
fonte
inspect.getfile(inspect.currentframe())
para obter o caminho do script em execução no momento.Não entendo por que ninguém está falando sobre isso, mas para mim a solução mais simples é usar imp.find_module ("modulename") (documentação aqui ):
Ele fornece uma tupla com o caminho na segunda posição:
A vantagem desse método sobre o "inspecionar" é que você não precisa importar o módulo para fazê-lo funcionar e pode usar uma string na entrada. Útil ao verificar os módulos chamados em outro script, por exemplo.
EDIT :
No python3, o
importlib
módulo deve fazer:Doc de
importlib.util.find_spec
:fonte
importlib.machinery.PathFinder().find_module("os").get_filename()
Alternativa maisimp.find_module
curta que eu encontrei no Python3 +. Se alguém está procurando o uso deimportlib.util.find_spec
.Isso foi trivial.
Cada módulo possui uma
__file__
variável que mostra seu caminho relativo de onde você está agora.Portanto, obter um diretório para o módulo notificá-lo é simples como:
fonte
fonte
__file__
é apenas dir / test.py, o abspath envolve o cwd para concluir o nome do caminho que não é o resultado desejado, mas se você importar um módulo,m.__file__
obtém o resultado desejado.Fonte
fonte
Utilitário de Linha de Comando
Você pode ajustá-lo para um utilitário de linha de comando,
Crio
/usr/local/bin/python-which
Torne executável
fonte
Por isso, passei bastante tempo tentando fazer isso com o py2exe. O problema era obter a pasta base do script, se ele estava sendo executado como um script python ou como um executável py2exe. Também para que funcione se estava sendo executado a partir da pasta atual, de outra pasta ou (essa foi a mais difícil) do caminho do sistema.
Eventualmente, usei essa abordagem, usando sys.frozen como um indicador de execução no py2exe:
fonte
você pode simplesmente importar seu módulo, clicar no nome e obter o caminho completo
fonte
Se você deseja recuperar o caminho raiz do pacote de qualquer um de seus módulos, o seguinte funciona (testado no Python 3.6):
O
__init__.py
caminho principal também pode ser referenciado usando em__file__
vez disso.Espero que isto ajude!
fonte
Se a única ressalva de uso
__file__
for atual, o diretório relativo estiver em branco (ou seja, ao executar como um script a partir do mesmo diretório em que o script está), uma solução trivial será:E o resultado:
O truque está
or '.'
após adirname()
ligação. Ele define o diretório como.
, o que significa diretório atual e é um diretório válido para qualquer função relacionada ao caminho.Assim, o uso
abspath()
não é realmente necessário. Mas se você o usar de qualquer maneira, o truque não será necessário:abspath()
aceita caminhos em branco e o interpreta adequadamente como o diretório atual.fonte
os.path.dirname(os.path.abspath(__file__))
porque, assim, você não precisa se preocupar com caminhos relativos. Uma oportunidade a menos para erros.Eu gostaria de contribuir com um cenário comum (no Python 3) e explorar algumas abordagens para ele.
A função interna open () aceita o caminho relativo ou absoluto como seu primeiro argumento. O caminho relativo é tratado como relativo ao diretório de trabalho atual, portanto, é recomendável passar o caminho absoluto para o arquivo.
Basta dizer, se você executar um arquivo de script com o seguinte código, é não garantiu que o
example.txt
arquivo será criado no mesmo diretório onde o arquivo de script está localizado:Para corrigir esse código, precisamos obter o caminho para o script e torná-lo absoluto. Para garantir que o caminho seja absoluto, simplesmente usamos a função os.path.realpath () . Para obter o caminho para o script, existem várias funções comuns que retornam vários resultados do caminho:
os.getcwd()
os.path.realpath('example.txt')
sys.argv[0]
__file__
Ambas as funções os.getcwd () e os.path.realpath () retornam resultados do caminho com base no diretório de trabalho atual . Geralmente não é o que queremos. O primeiro elemento da lista sys.argv é o caminho do script raiz (o script que você executa), independentemente de você chamar a lista no próprio script raiz ou em qualquer um de seus módulos. Pode ser útil em algumas situações. A variável __file__ contém o caminho do módulo do qual foi chamado.
O código a seguir cria corretamente um arquivo
example.txt
no mesmo diretório em que o script está localizado:fonte
Se você deseja conhecer o caminho absoluto do seu script, pode usar o objeto Path :
método cwd ()
método resolve ()
fonte
Nos módulos de um pacote python, tive que me referir a um arquivo que residia no mesmo diretório que o pacote. Ex.
Então, acima, eu tive que chamar maincli.py do módulo my_lib_a.py, sabendo que top_package e maincli.py estão no mesmo diretório. Aqui está como eu obtenho o caminho para maincli.py:
Com base na postagem de PlasmaBinturong, modifiquei o código.
fonte
Se você deseja fazer isso dinamicamente em um "programa", tente este código:
Meu argumento é que você talvez não saiba o nome exato do módulo para "codificá-lo". Pode ser selecionado em uma lista ou não estar em execução no momento para usar __file__.
(Eu sei, não vai funcionar no Python 3)
Tentei me livrar do problema "global", mas encontrei casos em que não funcionava. Acho que "execfile ()" pode ser emulado no Python 3 Como esse é um programa, ele pode ser facilmente colocado em um método ou módulo para reuso.
fonte
Se você o instalou usando o pip, "pip show" funciona muito bem ('Localização')
$ pip show detectron2
fonte
Aqui está um script bash rápido, caso seja útil para qualquer pessoa. Eu só quero poder definir uma variável de ambiente para que eu possa
pushd
o código.Exemplo de shell:
fonte