Como importo um módulo Python devido ao seu caminho relativo?
Por exemplo, se dirFoo
contém Foo.py
e dirBar
, e dirBar
contém Bar.py
, como faço Bar.py
para importar Foo.py
?
Aqui está uma representação visual:
dirFoo\
Foo.py
dirBar\
Bar.py
Foo
deseja incluir Bar
, mas a reestruturação da hierarquia de pastas não é uma opção.
python
relative-path
python-import
Jude Allred
fonte
fonte
Respostas:
Supondo que os dois diretórios sejam pacotes reais do Python (o
__init__.py
arquivo está dentro deles), aqui está uma solução segura para a inclusão de módulos em relação à localização do script.Suponho que você queira fazer isso, porque você precisa incluir um conjunto de módulos com seu script. Eu uso isso na produção em vários produtos e funciona em muitos cenários especiais, como: scripts chamados de outro diretório ou executados com python execute em vez de abrir um novo intérprete.
Como um bônus, essa abordagem permite forçar o Python a usar seu módulo em vez dos instalados no sistema.
Atenção! Eu realmente não sei o que está acontecendo quando o módulo atual está dentro de um
egg
arquivo. Provavelmente também falha.fonte
os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]) + "/subfolder")
Do NOT adicionar a subpasta antesabspath
, pois isso faz com que erros graves.cmd_subfolder
) diretamente à minha resposta. obrigado!realpath
já gera caminhos absolutos, portanto não precisoabspath
. Tambémos.path.dirname
pode ser usado em vez de dividir, tornando a indexação[0]
obsoleta. A linha seria então:os.path.realpath(os.path.dirname(inspect.getfile(inspect.currentframe())))
Certifique-se de que o dirBar tenha o
__init__.py
arquivo - isso transforma um diretório em um pacote Python.fonte
sys.path
, a presença de__init__.py
nodirBar
diretório não ajudará muito.__init.py__
funcionará apenas quando o diretório já estiver no sys.path e, no meu caso, não estava. Solução por "sorin" (aceito) sempre funciona.sys.path
pergunta? Talvez houvesse algo omitido que não vimos ou conhecemos?Você também pode adicionar o subdiretório ao seu caminho Python para que ele seja importado como um script normal.
fonte
sys.path.append(os.path.dirname(__file__) + "/relative/path/to/module")
sys.path.append(__name__ if __name__ != '__main__' else __loader__.fullname)
sys.path.insert(0, <path to dirFoo>)
como ele carregará este módulo antes dos módulos de mesmo nome armazenados em outro local.fonte
os.path.join()
vez de ingressar com '/', que será quebrado nas janelas (coxas).os.path.abspath(os.path.join(__file__,'..','lib'))
?Basta fazer coisas simples para importar o arquivo .py de uma pasta diferente.
Digamos que você tenha um diretório como:
Em seguida, basta manter um arquivo vazio na pasta lib como nomeado
E então use
Mantenha o
__init__.py
arquivo em todas as pastas da hierarquia do módulo de importação.fonte
Se você estruturar seu projeto desta maneira:
Então, no Foo.py, você poderá:
Ou:
De acordo com o comentário de Tom, isso exige que a
src
pasta esteja acessível viasite_packages
ou no seu caminho de pesquisa. Além disso, como ele menciona,__init__.py
é implicitamente importado quando você importa pela primeira vez um módulo nesse pacote / diretório. Normalmente__init__.py
é simplesmente um arquivo vazio.fonte
from dirFoo import Foo
para dizerFoo.bla()
. Se usarimport dirFoo.Foo
um deve usardirFoo.Foo.bla()
- muito feio, mesmo sem estojo de camelo.O método mais fácil é usar sys.path.append ().
No entanto, você também pode estar interessado no módulo imp . Ele fornece acesso a funções internas de importação.
Isso pode ser usado para carregar módulos dinamicamente quando você não sabe o nome de um módulo.
Eu usei isso no passado para criar uma interface do tipo plug-in para um aplicativo, onde o usuário escreveria um script com funções específicas do aplicativo e soltaria o script em um diretório específico.
Além disso, essas funções podem ser úteis:
fonte
Este é o PEP relevante:
http://www.python.org/dev/peps/pep-0328/
Em particular, presumindo que o dirFoo seja um diretório acima do dirBar ...
Em dirFoo \ Foo.py:
fonte
A maneira mais fácil, sem qualquer modificação no seu script, é definir a variável de ambiente PYTHONPATH. Como o sys.path é inicializado nesses locais:
Apenas corra:
Você sys.path contém o caminho acima, como mostrado abaixo:
fonte
Na minha opinião, a melhor opção é colocar __ init __.py na pasta e chamar o arquivo com
Não é recomendável usar sys.path.append () porque algo pode dar errado se você usar o mesmo nome de arquivo que o pacote python existente. Não testei isso, mas isso será ambíguo.
fonte
from dirBar.Bar import *
funciona, mas nãofrom dirBar.Bar import Bar
. você sabe por que * funciona? e se eu tivesse vários arquivos no dirBar / e quisesse pegar apenas alguns deles (usando um método como o que você postou aqui)?from dirBar import Bar
.from
indica a fonte, e tudo oimport
que se segue é o que pegar dessa fonte.from dirBar.Bar import Bar
significa "Da fonte, importe a própria fonte", o que não faz sentido. os*
através de meios, "me dar tudo a partir da fonte"A maneira rápida e suja para usuários de Linux
Se você está apenas mexendo e não se importa com problemas de implantação, pode usar um link simbólico (supondo que seu sistema de arquivos o suporte) para tornar o módulo ou pacote diretamente visível na pasta do módulo solicitante.
ou
Nota: Um "módulo" é qualquer arquivo com extensão .py e "pacote" é qualquer pasta que contém o arquivo
__init__.py
(que pode ser um arquivo vazio). Do ponto de vista de uso, os módulos e pacotes são idênticos - ambos expõem suas "definições e instruções" contidas conforme solicitado peloimport
comando.Veja: http://docs.python.org/2/tutorial/modules.html
fonte
ao invés de:
apenas no caso de haver outro dirBar instalado e confundir um leitor foo.py.
fonte
Nesse caso, para importar Bar.py para Foo.py, primeiro eu transformaria essas pastas em pacotes Python da seguinte forma:
Então eu faria isso no Foo.py:
Se eu quisesse que o namespace se parecesse com Bar. seja qual for , ou
Se eu quisesse o espaço para nome dirBar.Bar. tanto faz . Este segundo caso é útil se você tiver mais módulos no pacote dirBar.
fonte
Adicione um arquivo __init__.py :
Em seguida, adicione esse código ao início do Foo.py:
fonte
dirBar
já é um pacote de Python (pela existência dedirBar/__init__.py
), não há necessidade de anexardirBar
asys.path
, não? A declaraçãoimport Bar
deFoo.py
deve ser suficiente.Exemplo de sys.path relativo:
Com base nesta resposta.
fonte
Bem, como você mencionou, geralmente você quer ter acesso a uma pasta com seus módulos em relação à onde seu script principal é executado, então você apenas os importa.
Solução:
Eu tenho o script
D:/Books/MyBooks.py
e alguns módulos (como oldies.py). Preciso importar do subdiretórioD:/Books/includes
:Coloque um
print('done')
dentrooldies.py
para verificar se tudo está indo bem. Dessa maneira, sempre funciona porque, pela definição do Pythonsys.path
, inicializada na inicialização do programa, o primeiro item desta listapath[0]
, é o diretório que contém o script usado para chamar o intérprete do Python.Se o diretório do script não estiver disponível (por exemplo, se o intérprete for chamado interativamente ou se o script for lido a partir da entrada padrão),
path[0]
será a string vazia, que instrui o Python a pesquisar os módulos no diretório atual primeiro. Observe que o diretório do script é inserido antes das entradas inseridas como resultado dePYTHONPATH
.fonte
site.addsitedir(sys.path[0]+'/includes')
) no meu primeiro programa Python simples break_time.py: https://github.com/ltfschoen/PythonTest . Eu uso o sistema: MacOS v10.11.5, Python 2.7.12, IDLE IDE 2.7.12, Tk 8.5.9Simplesmente você pode usar:
from Desktop.filename import something
Exemplo:
o código:
Mas certifique-se de criar um arquivo vazio chamado "
__init__.py
" nesse diretóriofonte
import something
então eu disse para torná-lo mais fácil*
, basicamente, não é bom para a memória RAM e também se 2 funções tem o mesmo nome que vai em massa o seu códigoOutra solução seria instalar o pacote py-require e, em seguida, usar o seguinte em
Foo.py
fonte
require()
função, você pode dar uma olhada no meu projeto Node.py: github.com/nodepy/nodepyAqui está uma maneira de importar um arquivo de um nível acima, usando o caminho relativo.
Basicamente, basta mover o diretório ativo para um nível (ou qualquer local relativo), adicione-o ao seu caminho e, em seguida, mova o diretório ativo de volta para onde começou.
fonte
Eu não sou experiente em python, portanto, se houver algo errado em minhas palavras, apenas me diga. Se sua hierarquia de arquivos estiver organizada assim:
module_1.py
define uma função chamadafunc_1()
, module_2.py :e você executa
python module_2.py
no cmd, ele executa o quefunc_1()
define. Geralmente é assim que importamos os mesmos arquivos de hierarquia. Mas quando você escrevefrom .module_1 import func_1
emmodule_2.py
, interpretador Python vai dizerNo module named '__main__.module_1'; '__main__' is not a package
. Portanto, para corrigir isso, mantemos a alteração que acabamos de fazer e movemos os dois módulos para um pacote e fazemos um terceiro módulo como chamador para executarmodule_2.py
.main.py :
Mas a razão por que adicionar um
.
antesmodule_1
emmodule_2.py
é que se nós não fazemos isso e corrermain.py
, interpretador Python vai dizerNo module named 'module_1'
, isso é um pouco complicado,module_1.py
é bem ao ladomodule_2.py
. Agora eu deixofunc_1()
emmodule_1.py
fazer alguma coisa:que
__name__
registra quem chama func_1. Agora mantemos o.
antesmodule_1
, executemain.py
, ele será impressopackage_1.module_1
, nãomodule_1
. Indica que quem telefonafunc_1()
está na mesma hierarquia quemain.py
, o.
que implica quemodule_1
está na mesma hierarquia quemodule_2.py
ele. Portanto, se não houver um ponto,main.py
ele reconhecerámodule_1
na mesma hierarquia que ele, ele poderá reconhecerpackage_1
, mas não o que "está abaixo" dele.Agora vamos complicar um pouco. Você tem um
config.ini
e um módulo define uma função para lê-la na mesma hierarquia que 'main.py'.E, por algum motivo inevitável, é necessário chamá-lo com
module_2.py
, portanto, ele deve ser importado da hierarquia superior. module_2.py :Dois pontos significam importação da hierarquia superior (acesso de três pontos superior a superior e assim por diante). Agora corremos
main.py
, o intérprete vai dizer:ValueError:attempted relative import beyond top-level package
. O "pacote de nível superior" aqui émain.py
. Só porqueconfig.py
está ao ladomain.py
, eles estão na mesma hierarquia,config.py
não estão "abaixo"main.py
ou não são "liderados" pormain.py
, portanto estão alémmain.py
. Para corrigir isso, a maneira mais simples é:Eu acho que isso coincide com o princípio de organizar a hierarquia de arquivos do projeto, você deve organizar módulos com funções diferentes em pastas diferentes e deixar apenas um chamador de fora, e importar como quiser.
fonte
Isso também funciona e é muito mais simples do que qualquer coisa com o
sys
módulo:fonte
Me chame de muito cauteloso, mas eu gosto de tornar o meu mais portátil porque não é seguro supor que os arquivos sempre estarão no mesmo lugar em todos os computadores. Pessoalmente, tenho o código para procurar o caminho do arquivo primeiro. Eu uso o Linux para que o meu fique assim:
Isso é claro, a menos que você planeje agrupá-las. Mas se for esse o caso, você realmente não precisa de dois arquivos separados.
fonte