ModuleNotFoundError: O que significa __main__ não é um pacote?

208

Estou tentando executar um módulo no console. A estrutura do meu diretório é esta:

insira a descrição da imagem aqui

Estou tentando executar o módulo p_03_using_bisection_search.py, no problem_set_02diretório usando:

$ python3 p_03_using_bisection_search.py

O código dentro p_03_using_bisection_search.pyé:

__author__ = 'm'


from .p_02_paying_debt_off_in_a_year import compute_balance_after


def compute_bounds(balance: float,
                   annual_interest_rate: float) -> (float, float):

    # there is code here, but I have omitted it to save space
    pass


def compute_lowest_payment(balance: float,
                           annual_interest_rate: float) -> float:

    # there is code here, but I have omitted it to save space
    pass    

def main():
    balance = eval(input('Enter the initial balance: '))
    annual_interest_rate = eval(input('Enter the annual interest rate: '))

    lowest_payment = compute_lowest_payment(balance, annual_interest_rate)
    print('Lowest Payment: ' + str(lowest_payment))


if __name__ == '__main__':
    main()

Estou importando uma função na p_02_paying_debt_off_in_a_year.pyqual o código é:

__author__ = 'm'


def compute_balance(balance: float,
                    fixed_payment: float,
                    annual_interest_rate: float) -> float:

    # this is code that has been omitted
    pass


def compute_balance_after(balance: float,
                          fixed_payment: float,
                          annual_interest_rate: float,
                          months: int=12) -> float:

    # Omitted code
    pass


def compute_fixed_monthly_payment(balance: float,
                                  annual_interest_rate: float) -> float:

    # omitted code
    pass


def main():
    balance = eval(input('Enter the initial balance: '))
    annual_interest_rate = eval(
        input('Enter the annual interest rate as a decimal: '))
    lowest_payment = compute_fixed_monthly_payment(balance,
                                                   annual_interest_rate)
    print('Lowest Payment: ' + str(lowest_payment))


if __name__ == '__main__':
    main()

Eu estou recebendo o seguinte erro:

ModuleNotFoundError: No module named '__main__.p_02_paying_debt_off_in_a_year'; '__main__' is not a package

Não tenho ideia de como resolver esse problema. Tentei adicionar um __init__.pyarquivo, mas ele ainda não está funcionando.

lmiguelvargasf
fonte
3
Não é seu problema, mas eu só queria divulgá-lo: eval(input...provavelmente não é uma ótima idéia. Gostaria de analisá-lo em vez de abrir a oportunidade para execução arbitrária de código.
precisa saber é o seguinte
2
Aposto que essa parte eval(input(...foi sugerida por 2to3. Eu fiz isso comigo hoje. feliz que eu não segui-lo de sugestões blindling
ckot

Respostas:

238

Simplesmente remova o ponto da importação relativa e faça:

from p_02_paying_debt_off_in_a_year import compute_balance_after
Moses Koledoye
fonte
56
você resolve isso. Por que a importação relativa não está funcionando, mesmo se eu adicionar __init__.py?
Lmiguelvargasf
23
A resposta aceita não está funcionando para mim. Você poderia expandir a resposta adicionando uma configuração de exemplo minimalista?
Pranasas
13
Isso funciona para mim (dentro de um pacote, ou seja, com um vazio __init__.pyna mesma pasta), embora meu PyCharm (2018.2.4) marque isso como uma "Referência não resolvida" e não consiga concluir automaticamente a importação.
djvg
33
@djvg - Para corrigir o PyCharm, você pode marcar o diretório raiz como raiz de origem
Denis Yakovlev
12
Trabalhar com as importações do Python é irritante. É como se Python 3, PyCharm e MyPy estivessem rindo muito às nossas custas. Como é que from ..sibling_pkg.nephew import my_functioné válido para PyCharm, mas resulta em ValueError: attempted relative import beyond top-level packagee MyPy Cannot find module named '.sibling_pkg.nephew'(observe um único "." No erro, não dois). No entanto, from sibling_pkg.nephew import my_functionfunciona como pretendido, não possui um erro MyPy, mas resulta em um erro PyCharm.
Ubiquibacon 16/07/19
86

Eu tenho o mesmo problema que você. Acho que o problema é que você usou a importação relativa in-package import. Não há__init__.py no seu diretório. Portanto, apenas importe como Moisés respondeu acima.

O principal problema que eu acho é quando você importa com um ponto:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

É equivalente a:

from __main__.p_02_paying_debt_off_in_a_year import compute_balance_after

onde __main__se refere ao seu módulo atual p_03_using_bisection_search.py.


Resumidamente, o intérprete não conhece sua arquitetura de diretório.

Quando o intérprete entra p_03.py, o script é igual a:

from p_03_using_bisection_search.p_02_paying_debt_off_in_a_year import compute_balance_after

e p_03_using_bisection_searchnão contém nenhum módulo ou instância chamada p_02_paying_debt_off_in_a_year.


Então, eu vim com uma solução mais limpa sem alterar os objetos de valor do ambiente python (depois de pesquisar como as solicitações são feitas na importação relativa):

A arquitetura principal do diretório é:

main.py

setup.py

---problem_set_02/

------__init__.py

------p01.py

------p02.py

------p03.py

Então escreva em __init__.py:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

Aqui __main__está__init__ , exatamente se refere ao móduloproblem_set_02 .

Então vá para main.py:

import problem_set_02

Você também pode escrever um setup.pypara adicionar um módulo específico ao ambiente.

hcnhcn012
fonte
9

Tente executá-lo como:

python3 -m p_03_using_bisection_search

Dan Keder
fonte
2

Se você criou um diretório e subdiretório, siga as etapas abaixo e lembre-se de que todo diretório deve ter __init__.pypara que ele seja reconhecido como um diretório.

  1. No seu script, inclua import syse sys.path, você poderá ver todos os caminhos disponíveis para o Python. Você deve poder ver seu diretório de trabalho atual.

  2. Agora importe o subdiretório e o respectivo módulo que você deseja usar: import subdir.subdir.modulename as abce agora você pode usar os métodos nesse módulo.

insira a descrição da imagem aqui

Como exemplo, você pode ver nesta captura de tela Eu tenho um diretório pai e dois subdiretórios e, nos segundos subdiretórios, eu tenho o módulo CommonFunction. À direita, meu console mostra que após a execução de sys.path, posso ver meu diretório de trabalho.

Gaurav Singh
fonte
1

Remova o ponto e importe absolute_import no início do seu arquivo

from __future__ import absolute_import

from p_02_paying_debt_off_in_a_year import compute_balance_after
Aminah Nuraini
fonte
1

Basta usar o nome da pasta principal na qual o arquivo .py está.

from problem_set_02.p_02_paying_debt_off_in_a_year import compute_balance_after
FanBek
fonte