Imagine esta estrutura de diretório:
app/
__init__.py
sub1/
__init__.py
mod1.py
sub2/
__init__.py
mod2.py
Estou codificando mod1
e preciso importar algo de mod2
. Como devo fazer isso?
Eu tentei, from ..sub2 import mod2
mas estou recebendo uma "Tentativa de importação relativa no pacote".
Eu procurei no Google, mas encontrei apenas sys.path
hacks de "manipulação". Não existe um caminho limpo?
Editar: todos os meus __init__.py
estão vazios no momento
Edit2: Eu estou tentando fazer isso porque sub2 contém classes que são compartilhados entre pacotes de sub ( sub1
, subX
, etc.).
Edit3: O comportamento que estou procurando é o mesmo descrito no PEP 366 (obrigado John B)
Respostas:
Todo mundo parece querer lhe dizer o que você deve fazer, em vez de apenas responder à pergunta.
O problema é que você está executando o módulo como '__main__' passando o mod1.py como argumento ao intérprete.
Do PEP 328 :
No Python 2.6, eles estão adicionando a capacidade de referenciar módulos em relação ao módulo principal. PEP 366 descreve a mudança.
Atualização : De acordo com Nick Coghlan, a alternativa recomendada é executar o módulo dentro do pacote usando a opção -m.
fonte
-m
switch, em vez de especificar diretamente o nome do arquivo.from sub2 import mod2
. Em seguida, para executar o mod1, de dentro do aplicativo, façapython -m sub1.mod1
.Aqui está a solução que funciona para mim:
Faço as importações relativas como
from ..sub2 import mod2
e, se quiser executarmod1.py
, vou para o diretório paiapp
e executo o módulo usando a opção python -m comopython -m app.sub1.mod1
.A verdadeira razão pela qual esse problema ocorre com as importações relativas é que as importações relativas funcionam ao obter a
__name__
propriedade do módulo. Se o módulo estiver sendo executado diretamente, ele__name__
será definido como__main__
e não conterá nenhuma informação sobre a estrutura do pacote. E é por isso que o python reclama dorelative import in non-package
erro.Portanto, usando a opção -m, você fornece as informações da estrutura do pacote ao python, através da qual ele pode resolver as importações relativas com êxito.
Eu encontrei esse problema várias vezes ao fazer importações relativas. E, depois de ler todas as respostas anteriores, ainda não consegui descobrir como resolvê-lo, de uma maneira limpa, sem precisar inserir o código padrão em todos os arquivos. (Embora alguns comentários tenham sido realmente úteis, obrigado a @ncoghlan e @XiongChiamiov)
Espero que isso ajude alguém que está lutando com um problema relativo de importações, porque passar pelo PEP não é realmente divertido.
fonte
-m
foi projetado para resolver.from . import some_module
.python main.py
.main.py
faz:import app.package_a.module_a
module_a.py
fazimport app.package_b.module_b
Alternativamente 2 ou 3 podem usar:
from app.package_a import module_a
Isso funcionará enquanto você tiver
app
no seu PITONONA.main.py
poderia estar em qualquer lugar então.Então, você escreve um
setup.py
para copiar (instalar) todo o pacote de aplicativos e subpacotes nas pastas python do sistema demain.py
destino e nas pastas de script do sistema de destino.fonte
"O Guido vê os scripts em execução em um pacote como um antipadrão" ( PEP-3122 rejeitado )
Passei tanto tempo tentando encontrar uma solução, lendo postagens relacionadas aqui no Stack Overflow e dizendo para mim mesmo "deve haver uma maneira melhor!". Parece que não há.
fonte
-m
switch:python -m app.sub1.mod1
ou invocar aapp.sub1.mod1.main()
partir de um script de nível superior (por exemplo, gerado a partir dos pontos de entrada dos setuptools definidos em setup.py).Isso é resolvido 100%:
Importe settings / local_setting.py em app / main.py:
main.py:
fonte
sys.path.insert(0, "../settings")
e depoisfrom local_settings import *
Estou usando esse trecho para importar módulos de caminhos, espero que ajude
fonte
explicação da
nosklo's
resposta com exemplosnota: todos os
__init__.py
arquivos estão vazios.app / package_a / fun_a.py
app / package_b / fun_b.py
main.py
se você executá-
$ python main.py
lo, retorna:from app.package_b import fun_b
from app.package_a.fun_a import print_a
então arquivo na pasta
package_b
usado arquivo na pastapackage_a
, que é o que você deseja. Direita??fonte
Infelizmente, este é um hack do sys.path, mas funciona muito bem.
Encontrei esse problema com outra camada: eu já tinha um módulo com o nome especificado, mas era o módulo errado.
o que eu queria fazer era o seguinte (o módulo em que eu estava trabalhando era o module3):
Observe que eu já instalei o mymodule, mas na minha instalação não tenho "mymodule1"
e eu receberia um ImportError porque estava tentando importar dos meus módulos instalados.
Eu tentei fazer um sys.path.append, e isso não funcionou. O que funcionou foi um sys.path.insert
É uma espécie de hack, mas conseguiu que tudo funcionasse! Portanto, lembre-se, se você deseja que sua decisão substitua outros caminhos , use sys.path.insert (0, caminho) para fazê-lo funcionar! Este foi um ponto de discórdia muito frustrante para mim, muitas pessoas dizem usar a função "anexar" ao sys.path, mas isso não funciona se você já tiver um módulo definido (acho um comportamento muito estranho)
fonte
sys.path.append('../')
funciona bem para mim (Python 3.5.2)Deixe-me colocar isso aqui para minha própria referência. Eu sei que não é um bom código Python, mas eu precisava de um script para um projeto em que estava trabalhando e queria colocar o script em um
scripts
diretório.fonte
Como o @EvgeniSergeev diz nos comentários ao OP, você pode importar o código de um
.py
arquivo em um local arbitrário com:Isso é retirado desta resposta SO .
fonte
Consulte http://docs.python.org/whatsnew/2.5.html#pep-328-absolute-and-relative-imports . Você poderia fazer
fonte
No documento Python ,
fonte
Achei mais fácil definir a variável de ambiente "PYTHONPATH" para a pasta superior:
então:
é claro, PYTHONPATH é "global", mas ainda não me causou problemas.
fonte
virtualenv
permite gerenciar suas instruções de importação.Além do que John B disse, parece que definir a
__package__
variável deve ajudar, em vez de mudar o__main__
que pode estragar outras coisas. Mas, tanto quanto pude testar, não funciona completamente como deveria.Eu tenho o mesmo problema e nem o PEP 328 nem o 366 resolvem o problema completamente, pois ambos, no final do dia, precisam que o cabeçalho do pacote seja incluído
sys.path
, tanto quanto eu possa entender.Também devo mencionar que não encontrei como formatar a string que deve ser inserida nessas variáveis. É
"package_head.subfolder.module_name"
ou o quê?fonte
Você precisa anexar o caminho do módulo para
PYTHONPATH
:fonte
sys.path
, já quesys.path
é inicializado a partir dePYTHONPATH
sys.path
precisa ser codificado no código fonte, ao contrário doPYTHONPATH
que é uma variável de ambiente e pode ser exportado.