ModuleNotFoundError: Что значит __main__ не является пакетом?

209

Я пытаюсь запустить модуль из консоли. Структура моего каталога такая:

введите описание изображения здесь

Я пытаюсь запустить модуль p_03_using_bisection_search.pyиз problem_set_02каталога, используя:

$ python3 p_03_using_bisection_search.py

Код внутри 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()

Я импортирую функцию, в p_02_paying_debt_off_in_a_year.pyкоторой код:

__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()

Я получаю следующую ошибку:

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

Я понятия не имею, как решить эту проблему. Я попытался добавить __init__.pyфайл, но он все еще не работает.

lmiguelvargasf
источник
3
Не ваша проблема, но я просто хотел выбросить это: eval(input...вероятно, это не очень хорошая идея. Я бы просто проанализировал это вместо того, чтобы открыть возможность для выполнения произвольного кода.
Carcigenicate,
2
Держу пари, что этот eval(input(...бит был предложен 2to3. Я сделал это сегодня со мной. рад, что я не следую его предложениям ослепительно
ckot

Ответы:

241

Просто удалите точку для относительного импорта и выполните:

from p_02_paying_debt_off_in_a_year import compute_balance_after
Моисей Коледое
источник
56
Вы решаете это. Почему относительный импорт не работает, даже если я добавлю __init__.py?
lmiguelvargasf
23
Принятый ответ не работает для меня. Не могли бы вы расширить ответ, добавив минималистичный пример настройки?
Пранас
13
Это работает для меня (внутри пакета, то есть с пустым __init__.pyв той же папке), хотя мой PyCharm (2018.2.4) помечает это как «неразрешенную ссылку» и не может автоматически завершить импорт.
DJVG
33
@djvg - Чтобы исправить PyCharm, вы можете пометить корневой каталог как источник root
Денис Яковлев
12
Работа с импортом Python бесит. Как будто Python 3, PyCharm и MyPy все смеются за наш счет. Как это from ..sibling_pkg.nephew import my_functionдействительно для PyCharm, но приводит к ValueError: attempted relative import beyond top-level packageи MyPy Cannot find module named '.sibling_pkg.nephew'(обратите внимание на один «.» В ошибке, а не два). Тем не менее, from sibling_pkg.nephew import my_functionработает как задумано, не имеет ошибки MyPy, но приводит к ошибке PyCharm.
убиквибакон
86

У меня та же проблема, что и у вас. Я думаю, проблема в том, что вы использовали относительный импорт в in-package import. Там нет __init__.pyв вашем каталоге. Так что просто импортируйте, как Моисей ответил выше.

Основная проблема, которую я думаю, это когда вы импортируете с точкой:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

Это эквивалентно:

from __main__.p_02_paying_debt_off_in_a_year import compute_balance_after

где __main__относится к вашему текущему модулю p_03_using_bisection_search.py.


Вкратце, интерпретатор не знает вашей архитектуры каталогов.

Когда переводчик входит p_03.py, сценарий равен:

from p_03_using_bisection_search.p_02_paying_debt_off_in_a_year import compute_balance_after

и p_03_using_bisection_searchне содержит никаких вызванных модулей или экземпляров p_02_paying_debt_off_in_a_year.


Поэтому я пришел к более чистому решению без изменения ценностей среды Python (после просмотра того, как запросы выполняют относительный импорт):

Основная архитектура каталога:

main.py

setup.py

---problem_set_02/

------__init__.py

------p01.py

------p02.py

------p03.py

Тогда напишите в __init__.py:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

Вот __main__это__init__ , это точно относится к модулю problem_set_02.

Затем перейдите к main.py:

import problem_set_02

Вы также можете написать, setup.pyчтобы добавить определенный модуль в среду.

hcnhcn012
источник
9

Попробуйте запустить его как:

python3 -m p_03_using_bisection_search

Дэн Кедер
источник
2

Если вы создали каталог и подкаталог, следуйте приведенным ниже инструкциям и имейте в виду, что все каталоги должны быть __init__.pyраспознаны как каталог.

  1. В вашем скрипте include import sysи sys.pathвы сможете увидеть все пути, доступные для Python. Вы должны быть в состоянии увидеть ваш текущий рабочий каталог.

  2. Теперь импортируйте подкаталог и соответствующий модуль, который вы хотите использовать, используя: import subdir.subdir.modulename as abcи теперь вы можете использовать методы этого модуля.

введите описание изображения здесь

В качестве примера, вы можете увидеть на этом скриншоте у меня есть один родительский каталог и два подкаталога, а во втором подкаталоге у меня есть модуль CommonFunction. Справа моя консоль показывает, что после выполнения sys.pathя вижу свой рабочий каталог.

Гаурав Сингх
источник
1

Удалите точку и импортируйте absolute_import в начале вашего файла

from __future__ import absolute_import

from p_02_paying_debt_off_in_a_year import compute_balance_after
Амина Нураини
источник
1

Просто используйте имя основной папки, в которой находится .py файл.

from problem_set_02.p_02_paying_debt_off_in_a_year import compute_balance_after
FanBek
источник