Pergunta

Eu quero detectar se o módulo mudou. Agora, usando inotify é simples, você só precisa saber o diretório que você deseja obter notificações.

Como faço para recuperar o caminho de um módulo em python?

Foi útil?

Solução

import a_module
print(a_module.__file__)

Será que realmente dar-lhe o caminho para o arquivo .pyc que foi carregado, pelo menos no Mac OS X. Então eu acho que você pode fazer:

import os
path = os.path.dirname(a_module.__file__)

Você também pode tentar:

path = os.path.abspath(a_module.__file__)

Para obter o diretório do módulo.

Outras dicas

Há módulo inspect em python.

documentação oficial

O inspecionar módulo fornece várias funções úteis para ajudar a obter informações sobre os objetos ao vivo, como módulos, classes, métodos, funções, tracebacks, objetos de quadro, e objectos código. Por exemplo, ele pode ajudá-lo a examinar o conteúdo de uma classe, recuperar a fonte código de um método, extrair e formatar a lista de argumentos para uma função, ou obter todas as informações que você precisa 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'

Como as outras respostas já disse, a melhor maneira de fazer isso é com __file__ (demonstrado novamente abaixo). No entanto, há uma ressalva importante, o que é que __file__ não existe se você estiver executando o módulo sobre a sua própria (ou seja, como __main__).

Por exemplo, digamos que você tem dois arquivos (ambos dos quais são em seu PYTHONPATH):

#/path1/foo.py
import bar
print(bar.__file__)

e

#/path2/bar.py
import os
print(os.getcwd())
print(__file__)

Running foo.py dará 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 bar.py por conta própria, você vai ter:

/path2                              # "print(os.getcwd())" still works fine
Traceback (most recent call last):  # but __file__ doesn't exist if bar.py is running as main
  File "/path2/bar.py", line 3, in <module>
    print(__file__)
NameError: name '__file__' is not defined 

Espero que isso ajude. Este custo ressalva me muito tempo e confusão ao testar as outras soluções apresentadas.

Vou tentar abordar algumas variações sobre esta questão, bem como:

  1. encontrar o caminho do script chamado
  2. encontrar o caminho do script atualmente em execução
  3. encontrar o diretório do script chamado

(Algumas dessas perguntas foram feitas no SO, mas foram fechadas como duplicatas e redirecionado aqui.)

dicas de uso de __file__

Para um módulo que você importou:

import something
something.__file__ 

irá retornar o absoluta caminho do módulo. No entanto, dada a foo.py roteiro folowing:

#foo.py
print '__file__', __file__

chamá-lo com 'foo.py python' retornará simplesmente 'foo.py'. Se você adicionar um shebang:

#!/usr/bin/python 
#foo.py
print '__file__', __file__

e chamá-lo usando ./foo.py, ele irá retornar './foo.py'. Chamá-lo a partir de um diretório diferente (por exemplo, colocar foo.py no bar diretório), em seguida, chamar qualquer

python bar/foo.py

ou adicionando um shebang e executar o arquivo diretamente:

bar/foo.py

retornará 'bar / foo.py' (o em relação path).

Encontrar o diretório

Agora, indo de lá para obter o diretório, os.path.dirname(__file__) também pode ser complicado. Pelo menos no meu sistema, ele retorna uma string vazia se você chamá-lo a partir do mesmo diretório do arquivo. ex.

# foo.py
import os
print '__file__ is:', __file__
print 'os.path.dirname(__file__) is:', os.path.dirname(__file__)

saída será:

__file__ is: foo.py
os.path.dirname(__file__) is: 

Em outras palavras, ele retorna uma cadeia vazia, de modo que este não parece confiável, se você quiser usá-lo para a corrente arquivo (em oposição à arquivo de um módulo importado). Para contornar este problema, você pode envolvê-lo em uma chamada para abspath:

# foo.py
import 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__))

que gera algo como:

os.path.abspath(__file__) is: /home/user/bar/foo.py
os.path.dirname(os.path.abspath(__file__)) is: /home/user/bar

Note que abspath () não resolver links simbólicos. Se você quiser fazer isso, use realpath () em vez. Por exemplo, fazendo um file_import_testing_link link simbólico 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__)

execução vai imprimir caminhos absolutos algo como:

abspath(__file__) /home/user/file_test_link
realpath(__file__) /home/user/file_test.py

file_import_testing_link -> file_import_testing.py

Usando inspecionar

@SummerBreeze menciona usando o inspecionar módulo .

Isso parece funcionar bem, e é bastante concisa, para os módulos importados:

import os
import inspect
print 'inspect.getfile(os) is:', inspect.getfile(os)

obedientemente retorna o caminho absoluto. No entanto, para encontrar o caminho do script atualmente em execução, eu não vi uma maneira de usá-lo.

Eu não entendo por que ninguém está falando sobre isso, mas para mim a solução mais simples é usando imp.find_module ( "modulename") (documentação here ):

import imp
imp.find_module("os")

Ela dá 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 deste método sobre o "inspecionar" um é que você não precisa importar o módulo para fazer o trabalho, e você pode usar uma corda na entrada. Útil ao verificar módulos chamados em outro script, por exemplo.

Editar :

Em python3, módulo importlib deve fazer:

Doc de importlib.util.find_spec:

Voltar a especificação para o módulo especificado.

Em primeiro lugar, sys.modules é verificado para ver se o módulo já foi importado. Se assim for, então sys.modules [nome]. especificação é retornado. Se isso acontecer a ser definido como Nenhum, então ValueError é levantada. Se o módulo não está na sys.modules, então sys.meta_path é pesquisada por uma especificação apropriada com o valor de 'caminho' dado aos localizadores. Nenhum é devolvido se não houver especificação poderia ser encontrada.

Se o nome é para submodule (contém um ponto), o módulo pai é importados automaticamente.

O nome e pacote argumentos funcionam da mesma forma importlib.import_module (). Em outras palavras, os nomes dos módulos relativos (com os principais pontos) de trabalho.

Este foi trivial.

Cada módulo tem uma variável __file__ que mostra a sua relativa do local onde você está agora.

Portanto, a obtenção de um diretório para o módulo para notificá-la é simples como:

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

Command Line Utility

Você pode ajustá-lo para um utilitário de linha de comando,

python-which <package name>

 enter descrição da imagem aqui


Criar /usr/local/bin/python-which

#!/usr/bin/env python

import importlib
import os
import sys

args = sys.argv[1:]
if len(args) > 0:
    module = importlib.import_module(args[0])
    print os.path.dirname(module.__file__)

Faça-o executável

sudo chmod +x /usr/local/bin/python-which

Então eu passei uma boa quantidade de tempo tentando fazer isso com py2exe O problema era fazer com que a pasta base do roteiro se ele estava sendo executado como um script python ou como um executável py2exe. Também tê-lo funcionar se ele estava sendo executado a partir da pasta atual, outra pasta ou (este foi o mais difícil) do caminho do sistema.

Finalmente, eu usei essa abordagem, usando sys.frozen como um indicador de correr em 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__))
import module
print module.__path__

Pacotes apoiar um atributo mais especial, __path__. Isto é inicializado para ser uma lista contendo o nome da exploração diretório __init__.py do pacote antes de o código nesse arquivo é executado. Esta variável pode ser modificado; isso afeta futuras pesquisas para módulos e subpackages contido no pacote.

Enquanto este recurso não é muitas vezes necessário, ele pode ser usado para estender o conjunto de módulos encontrado em um pacote.

Fonte

você pode simplesmente importar o módulo em seguida, bateu o seu nome e você vai ter o seu caminho completo

>>> import os
>>> os
<module 'os' from 'C:\\Users\\Hassan Ashraf\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\os.py'>
>>>

Se a única ressalva de usar __file__ é quando a corrente diretório, relativa está em branco (ou seja, quando executado como um script do mesmo diretório onde está o script), em seguida, uma solução trivial é:

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á em or '.' após a chamada dirname(). Ele define o dir como ., o que significa diretório atual e é um diretório válido para qualquer função caminho-relacionado.

Assim, usando abspath() não é realmente necessário. Mas se você usá-lo de qualquer maneira, o truque não é necessário:. abspath() aceita caminhos em branco e devidamente interpreta como o diretório atual

Eu gostaria de contribuir com um cenário comum (em Python 3) e explorar algumas abordagens a ele.

A built-in função open () aceita tanto em relação ou caminho absoluto como seu primeiro argumento. O caminho relativo é tratado como relativo ao diretório de trabalho atual que por isso é recomendado para 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 arquivo example.txt será criado no mesmo diretório onde o arquivo de script está localizado:

with open('example.txt', 'w'):
    pass

Para corrigir esse código que precisa para obter o caminho para o script e torná-la absoluta. Para garantir o caminho para ser absoluta nós simplesmente usar a OS .path.realpath () função . Para obter o caminho para o script existem várias funções comuns que retornam vários resultados de caminho:

  • os.getcwd()
  • os.path.realpath('example.txt')
  • sys.argv[0]
  • __file__

os.getcwd () e < a href = "https://docs.python.org/3/library/os.path.html#os.path.realpath" rel = "nofollow noreferrer"> os.path.realpath () caminho de retorno resultados com base no diretório de trabalho atual . Geralmente não o que queremos. O primeiro elemento da href="https://docs.python.org/3/library/sys.html#sys.argv" rel="nofollow noreferrer"> lista é o < em> caminho do script root (o script é executado), independentemente de você chamar a lista no script raiz em si ou em qualquer um dos seus módulos. Pode vir a calhar em algumas situações. A variável __file__ contém caminho do módulo a partir do qual ele foi chamado .


O código a seguir corretamente cria uma example.txt arquivo no mesmo diretório onde o script está localizado:

filedir = os.path.dirname(os.path.realpath(__file__))
filepath = os.path.join(filedir, 'example.txt')

with open(filepath, 'w'):
    pass

De dentro de módulos de um pacote de python que eu tinha para se referir a um arquivo que residia no mesmo diretório como o pacote. Ex.

some_dir/
  maincli.py
  top_package/
    __init__.py
    level_one_a/
      __init__.py
      my_lib_a.py
      level_two/
        __init__.py
        hello_world.py
    level_one_b/
      __init__.py
      my_lib_b.py

Assim, em cima 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 obter o caminho para maincli.py:

import sys
import os
import imp


class ConfigurationException(Exception):
    pass


# inside of my_lib_a.py
def 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')

    if not os.path.exists(maincli_path):
        err_msg = 'This script expects that "maincli.py" be installed to the '\
        'same directory: "{0}"'.format(maincli_path)
        raise ConfigurationException(err_msg)

    return maincli_path

Com base na postagem por PlasmaBinturong eu modifiquei o código.

Se você quiser fazer isso de forma dinâmica em um "programa" tentar este código:
Meu ponto é, você não pode saber o nome exato do módulo "hardcode"-lo. Pode ser selecionada a partir de uma lista ou não ser em execução no momento de usar __file __.

(eu sei, não vai funcionar em 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'>

Eu tentei me livrar do problema "global", mas encontrou casos em que não fez trabalho Eu acho que "execfile ()" pode ser emulada em Python 3 Uma vez que este está em um programa, ele pode facilmente ser colocado em um método ou módulo para reutilização.

Se você gostaria de saber caminho absoluto do seu script que você pode usar Path objeto:

from pathlib import Path

print(Path().absolute())
print(Path().resolve('.'))
print(Path().cwd())
método

cwd ()

retornar um novo objeto de caminho que representa o diretório atual (como retornado por os.getcwd ())

resolve () método

Faça o caminho absoluto, resolver quaisquer links simbólicos. Um novo objeto de caminho é retornado:

Se você quiser recuperar o caminho raiz do pacote a partir de qualquer um dos seus módulos, as seguintes obras (testado em Python 3.6):

from . import __path__ as ROOT_PATH
print(ROOT_PATH)

A principal caminho __init__.py também pode ser referenciado usando __file__ vez.

Espero que isso ajude!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top