Como estruturar meu projeto Python para permitir que módulos nomeados sejam importados de subdiretórios
Esta é a minha estrutura de diretórios:
Projects
+ Project_1
+ Project_2
- Project_3
- Lib1
__init__.py # empty
moduleA.py
- Tests
__init__.py # empty
foo_tests.py
bar_tests.py
setpath.py
__init__.py # empty
foo.py
bar.py
Metas:
Ter uma estrutura de projeto organizadaPoder executar independentemente cada arquivo .py quando necessárioSer capaz de referenciar / importar os irmãos eprimo módulosMantenha todas as instruções de importação / de no início de cada arquivo.Consegui # 1 usando a estrutura acima
Consegui principalmente 2, 3 e 4 fazendo o seguinte (conforme recomendado poreste excelente guia)
Em qualquer pacote que precise acessar os módulos pai ou primo (como o diretório Tests acima), incluo um arquivo chamado setpath.py que possui o seguinte código:
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
sys.path.insert(0, os.path.abspath('.'))
sys.path.insert(0, os.path.abspath('...'))
Então, em cada módulo que precisa de acesso de pai / primo, como foo_tests.py, eu posso escrever uma boa lista limpa de importações como:
import setpath # Annoyingly, PyCharm warns me that this is an unused import statement
import foo.py
Dentro do setpath.py, a segunda e a terceira inserções não são estritamente necessárias para este exemplo, mas são incluídas como uma etapa de solução de problemas.
Meu problema é que isso funciona apenas para importações que fazem referência direta ao nome do módulo e não para importações que fazem referência ao pacote. Por exemplo, dentro de bar_tests.py, nenhuma das duas instruções abaixo funciona ao executar bar_tests.pydiretamente.
import setpath
import Project_3.foo.py # Error
from Project_3 import foo # Error
Eu recebo o erro "ImportError: nenhum módulo chamado 'Project_3'".
O que é estranho é que eu posso executar o arquivo diretamente de dentro do PyCharm e ele funciona bem. Eu sei que o PyCharm está fazendo mágica nos bastidores com oPython Path
variável para fazer tudo funcionar, mas não consigo descobrir o que é. Como o PyCharm simplesmente executa o python.exe e define algumas variáveis ambientais, deve ser possível clonar esse comportamento a partir do próprio script Python.
Por razões não muito pertinentes a essa pergunta, eu tenho que fazer referênciabar
usando oProject_3
qualificador.
Estou aberto a qualquer solução que cumpra o acima exposto, enquanto ainda atendo aos meus objetivos anteriores. Também estou aberto a uma estrutura de diretório alternativa, se houver uma que funcione melhor. Eu li oDocumento Python sobre importações e pacotes, mas ainda estou perdido. Eu acho que uma avenida possível pode ser definir manualmente o__path__
variável, mas não tenho certeza de qual delas precisa ser alterada ou para qual configuração.