ModuleNotFoundError: What does it mean __main__ is not a package? [duplicate]
Asked Answered
I

6

259

I am trying to run a module from the console. The structure of my directory is this:

enter image description here

I am trying to run the module p_03_using_bisection_search.py, from the problem_set_02 directory using:

$ python3 p_03_using_bisection_search.py

The code inside p_03_using_bisection_search.pyis:

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

I am importing a function that is in p_02_paying_debt_off_in_a_year.py which code is:

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

I am getting the following error:

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

I have no idea how to solve this issue. I have tried adding a __init__.py file, but it is still not working.

Ixion answered 23/1, 2017 at 22:40 Comment(2)
Not your issue, but I just wanted to throw it out there: eval(input... probably isn't a great idea. I'd just parse it instead of opening up the opportunity for arbitrary code execution.Chrysolite
i'd bet that eval(input(... bit was suggested by 2to3. I had it do that to me today. glad I don't follow it's suggestions blindlingIntended
F
296

Simply remove the dot for the relative import and do:

from p_02_paying_debt_off_in_a_year import compute_balance_after
Fahrenheit answered 23/1, 2017 at 22:44 Comment(11)
you solve it. Why is the relative import not working even if I add __init__.py?Ixion
The accepted answer is not working for me. Could you possibly expand the answer by adding a minimalistic example setup?Filmy
from myclass import SomeClass, here I got error for myclass and SomeClass but still this got worked for me.Derosa
This works for me (inside a package, i.e. with an empty __init__.py in the same folder), although my PyCharm (2018.2.4) marks this as an "Unresolved reference" and fails to autocomplete the import.Delate
@Delate - To fix PyCharm you can mark root directory as source rootPhonotypy
Warning: This fails when you create an entry_point console_script in setup.py while distributing the package. Also, VSCode fails to parse this (although thats the editor's fault).Sceptic
Working with Python's imports is infuriating. It is like Python 3, PyCharm, and MyPy are all having a big laugh at our expense. How is it that from ..sibling_pkg.nephew import my_function is valid for PyCharm, but results in ValueError: attempted relative import beyond top-level package and MyPy Cannot find module named '.sibling_pkg.nephew' (note a single "." in the error, not two). Yet, from sibling_pkg.nephew import my_function works as intended, doesn't have a MyPy error, but does result in a PyCharm error.Labe
I fixed this error by not naming my main script the same thing as its parent directory. I had my main script "app.py" in a folder "app", i.e. app/app.py. It contained the line import app.lib, which was intended to import the module app/lib.py. Raises ModuleNotFoundError: No module named 'app.lib'; 'app' is not a package. Fixed by renaming app/app.py to app/blabla.py.Elmerelmina
Extending the comment from @DenisYakovlev: To mark a directory as a sources root in PyCharm just right-click, "Mark Directory As", "Sources Root".Archaeo
@Labe may you never have the misfortune of trying to work with dependencies for any medium/large application.Suddenly
@MosesKoledoye, please explain why removing a dot works and not otherwise. Thank youOpiumism
C
113

I have the same issue as you did. I think the problem is that you used relative import in in-package import. There is no __init__.py in your directory. So just import as Moses answered above.

The core issue I think is when you import with a dot:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

It is equivalent to:

from __main__.p_02_paying_debt_off_in_a_year import compute_balance_after

where __main__ refers to your current module p_03_using_bisection_search.py.


Briefly, the interpreter does not know your directory architecture.

When the interpreter get in p_03.py, the script equals:

from p_03_using_bisection_search.p_02_paying_debt_off_in_a_year import compute_balance_after

and p_03_using_bisection_search does not contain any modules or instances called p_02_paying_debt_off_in_a_year.


So I came up with a cleaner solution without changing python environment valuables (after looking up how requests do in relative import):

The main architecture of the directory is:

main.py
setup.py
problem_set_02/
   __init__.py
   p01.py
   p02.py
   p03.py

Then write in __init__.py:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

Here __main__ is __init__ , it exactly refers to the module problem_set_02.

Then go to main.py:

import problem_set_02

You can also write a setup.py to add specific module to the environment.

Colter answered 29/9, 2017 at 17:47 Comment(0)
P
12

Try to run it as:

python3 -m p_03_using_bisection_search

Panjabi answered 18/7, 2018 at 7:39 Comment(0)
S
6

Just use the name of the main folder which the .py file is in.

from problem_set_02.p_02_paying_debt_off_in_a_year import compute_balance_after
Santamaria answered 3/5, 2020 at 8:26 Comment(0)
C
5

Remove the dot and import absolute_import in the beginning of your file

from __future__ import absolute_import

from p_02_paying_debt_off_in_a_year import compute_balance_after
Counterproposal answered 5/9, 2019 at 16:35 Comment(0)
C
2

If you have created directory and sub-directory, follow the steps below and please keep in mind all directory must have __init__.py to get it recognized as a directory.

  1. In your script, include import sys and sys.path, you will be able to see all the paths available to Python. You must be able to see your current working directory.

  2. Now import sub-directory and respective module that you want to use using: import subdir.subdir.modulename as abc and now you can use the methods in that module.

enter image description here

As an example, you can see in this screenshot I have one parent directory and two sub-directories and under second sub-directories I have the module CommonFunction. On the right my console shows that after execution of sys.path, I can see my working directory.

Cromwell answered 21/10, 2017 at 8:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.