Importar módulo da subpasta

104

Quero importar subpastas como módulos. Portanto, cada subpasta contém um __init__.py. Minha estrutura de pastas é assim:

src\
  main.py
  dirFoo\
    __init__.py
    foofactory.py
    dirFoo1\
      __init__.py
      foo1.py
    dirFoo2\
      __init__.py
      foo2.py

No meu script principal eu importo

from dirFoo.foofactory import FooFactory

Neste arquivo de fábrica, incluo os submódulos:

from dirFoo1.foo1 import Foo1
from dirFoo2.foo2 import Foo2

Se eu chamar minha foofactory, recebo o erro, esse python não pode importar os submódulos foo1 e foo2:

Traceback (most recent call last):
  File "/Users/tmp/src/main.py", line 1, in <module>
from dirFoo.foofactory import FooFactory
  File "/Users/tmp/src/dirFoo/foofactory.py", line 1, in    <module>
from dirFoo1.foo1 import Foo1
    ImportError: No module named dirFoo1.foo1
Razer
fonte

Respostas:

136

Não há necessidade de mexer com o seu PYTHONPATHou sys.pathaqui.

Para usar corretamente as importações absolutas em um pacote, você também deve incluir o nome do pacote "raiz", por exemplo:

from dirFoo.dirFoo1.foo1 import Foo1
from dirFoo.dirFoo2.foo2 import Foo2

Ou você pode usar importações relativas :

from .dirfoo1.foo1 import Foo1
from .dirfoo2.foo2 import Foo2
Rob Wouters
fonte
47
Uma coisa para lembrar! adicione __init__.pya cada subpasta da qual você está importando.
Aziz Alto,
6
Vazio __init__.pypode fazer o trabalho.
cerebrou
1
Qual seria a sintaxe se antes Foo1estivesse no diretório pai e outro codificado como from Foo1 import *. Existe uma maneira de obter o mesmo efeito para que você não precise prefixar tudo com Foo1?
jxramos
1
@AzizAlto: sem o seu comentário esta solução não é muito útil
Alex
21

Só para avisar aqui. (de um newbee, keviv22)

Nunca e para o seu próprio bem, nomeie as pastas ou arquivos com símbolos como "-" ou "_". Se você fez isso, poderá enfrentar alguns problemas. como o meu, digamos, embora seu comando para importação esteja correto, você não conseguirá importar com sucesso os arquivos desejados que estão disponíveis dentro dessas pastas nomeadas.

Nomenclatura de pasta inválida conforme a seguir:

  • Pasta de classes genéricas
  • Generic_Classes_Folder

nomes de pasta válidos para acima:

  • GenericClassesFolder ou Genericclassesfolder ou genericClassesFolder (ou assim, sem espaços ou símbolos especiais entre as palavras)

Que erro eu cometi:

considere a estrutura do arquivo.

Parent
   . __init__.py
   . Setup
     .. __init__.py
     .. Generic-Class-Folder
        ... __init__.py
        ... targetClass.py
   . Check
     .. __init__.py
     .. testFile.py

O que eu queria fazer?

  • de testFile.py, eu queria importar o arquivo 'targetClass.py' dentro do arquivo Generic-Class-Folder para usar a função chamada "functionExecute" no arquivo 'targetClass.py'

Que comando eu fiz?

  • de 'testFile.py', escreveu o comando, from Core.Generic-Class-Folder.targetClass import functionExecute
  • Tenho erros como SyntaxError: invalid syntax

Tentei muitas pesquisas e visualizei muitas perguntas sobre o stackoverflow e não consegui decidir o que deu errado. Eu cruzei meus arquivos várias vezes, usei o __init__.pyarquivo, inseri o caminho do ambiente e fiquei extremamente preocupado com o que deu errado ...

E depois de muito, muito tempo, descobri isso conversando com um amigo meu. Eu sou um pouco estúpido em usar essas convenções de nomenclatura. Nunca devo usar espaço ou símbolos especiais para definir um nome para qualquer pasta ou arquivo. Então, isso é o que eu queria transmitir. Tenha um bom dia!

(desculpe pela enorme postagem sobre isso ... apenas deixando minhas frustrações irem .... :) Obrigado!)

Vivek22
fonte
22
Espaços e travessões ("-") podem causar isso, mas os sublinhados ("_") ainda devem funcionar bem.
cowlinator
6

Defina sua variável de ambiente PYTHONPATH. Por exemplo, como este PYTHONPATH =.: .. (para a família * nix).

Além disso, você pode adicionar manualmente seu diretório atual (src no seu caso) ao pythonpath:

import os
import sys
sys.path.insert(0, os.getcwd())
Max Kamenkov
fonte
2

Digamos que seu projeto esteja estruturado desta forma:

+---MyPythonProject
|   +---.gitignore
|   +---run.py
|   |   +---subscripts
|   |   |   +---script_one.py
|   |   |   +---script_two.py

Dentro run.py, você pode importar os scripts um e dois:

from subscripts import script_one as One
from subscripts import script_two as Two

Agora, ainda dentro run.py, você poderá chamar seus métodos com:

One.method_from_one(param)
Two.method_from_two(other_param)
Flavio Wuensche
fonte
1

Basta criar um arquivo ___init____.py vazio e adicioná-lo na raiz, bem como em todos os subdiretórios / pastas do seu aplicativo Python onde você tem outros módulos Python.

Abhijit Pritam Dutta
fonte
-2

Teve problemas mesmo quando init .py existia na subpasta e tudo o que faltava era adicionar 'como' após a importação

from folder.file import Class as Class
import folder.file as functions
Tomas Trdla
fonte