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.

questionAnswers(2)

yourAnswerToTheQuestion