Não é possível importar * de um subdiretório em Python [duplicado]

Oct 26 2020

Estou procurando importar um conjunto de módulos de um subdiretório para um único módulo principal no diretório pai:

Projeto/

main.py
subdirectory/
    __init__.py
    timer.py
    example.py

Posso solicitar qualquer um dos arquivos .py individuais, como:

from subdirectory import timer.py

Mas, se eu executar o seguinte comando,

from subdirectory import *

e tento usar um módulo dentro desse subdiretório, recebo o seguinte erro:

File "My:\Path\Here\...", line 33, in main
t = timer.timer()
NameError: name 'timer' is not defined

Quero poder importar todos os arquivos em um lote, pois estou importando alguns módulos. Já adicionei um arquivo init .py em branco ao subdiretório. Há algo que estou perdendo?

Respostas

3 Selcuk Oct 26 2020 at 06:42

Você deve declarar seus nomes de módulos usando __all__em sua __init__.py:

__init__.py:

__all__ = ["timer", "example"]

Este comportamento está documentado :

A única solução é o autor do pacote fornecer um índice explícito do pacote. A importinstrução usa a seguinte convenção: se o __init__.pycódigo de um pacote define uma lista nomeada __all__, ela é considerada a lista de nomes de módulos que devem ser importados quando from package import *são encontrados.

2 AndréC.Andersen Oct 26 2020 at 06:48

Se você quiser apenas fazer as importações funcionarem, adicione subdirectory/__init__.pyo seguinte conteúdo:

from * import example
from * import timer

No entanto, se você quiser fazer isso com um número arbitrário de módulos (antigos e novos), acho que esta resposta pode ser o que você está procurando:

Você começa com a seguinte estrutura:

main.py
subdirectory/
subdirectory/__init__.py
subdirectory/example.py
subdirectory/timer.py

Em seguida, importe tudo subdirectoryde main.py:

from subdirectory import *
t = timer.timer()

Em seguida, adicione o seguinte ao subdirectory/__init__.pymódulo:

from os.path import dirname, basename, isfile, join
import glob
modules = glob.glob(join(dirname(__file__), "*.py"))
__all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not 
f.endswith('__init__.py')]

E para completar o subdirectory/timer.pymódulo:

def timer():
    return 42
Deep_Thoughts Oct 26 2020 at 06:34

As importações vão assim.

# if you have timer.py, import it as 
import timer

Tente adicionar __init__.pyao subdiretório. Agora será semelhante a:

Projeto/


    main.py
    subdirectory/
                 __init__.py
                 timer.py
                 example.py

Se isso não funcionar: no main.pyadd

import sys
sys.path.append("path/to/subdirectory") # replace with the path
import timer