ModuleNotFoundError: Qu'est-ce que cela signifie que __main__ n'est pas un package?

209

J'essaie d'exécuter un module à partir de la console. La structure de mon répertoire est la suivante:

entrez la description de l'image ici

J'essaie d'exécuter le module p_03_using_bisection_search.py, à partir du problem_set_02répertoire en utilisant:

$ python3 p_03_using_bisection_search.py

Le code à l'intérieur p_03_using_bisection_search.pyest:

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

J'importe une fonction dans p_02_paying_debt_off_in_a_year.pylaquelle le code est:

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

Je reçois l'erreur suivante:

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

Je ne sais pas comment résoudre ce problème. J'ai essayé d'ajouter un __init__.pyfichier, mais cela ne fonctionne toujours pas.

lmiguelvargasf
la source
3
Ce n'est pas votre problème, mais je voulais juste le dire: ce eval(input...n'est probablement pas une excellente idée. Je voudrais simplement l'analyser au lieu d'ouvrir la possibilité d'une exécution de code arbitraire.
Carcigenicate
2
je parie que ce eval(input(...bit a été suggéré par 2to3. Je l'ai fait me faire ça aujourd'hui. heureux de ne pas suivre ses suggestions aveuglantes
ckot

Réponses:

241

Supprimez simplement le point pour l'importation relative et faites:

from p_02_paying_debt_off_in_a_year import compute_balance_after
Moses Koledoye
la source
56
vous le résolvez. Pourquoi l'importation relative ne fonctionne-t-elle pas même si j'ajoute __init__.py?
lmiguelvargasf
23
La réponse acceptée ne fonctionne pas pour moi. Pourriez-vous éventuellement développer la réponse en ajoutant un exemple de configuration minimaliste?
Pranasas
13
Cela fonctionne pour moi (à l'intérieur d'un package, c'est-à-dire avec un vide __init__.pydans le même dossier), bien que mon PyCharm (2018.2.4) le marque comme une "référence non résolue" et ne parvienne pas à compléter automatiquement l'importation.
djvg
33
@djvg - Pour corriger PyCharm, vous pouvez marquer le répertoire racine comme racine source
Denis Yakovlev
12
Travailler avec les importations de Python est exaspérant. C'est comme si Python 3, PyCharm et MyPy rigolaient tous à nos dépens. Comment est-ce qui from ..sibling_pkg.nephew import my_functionest valide pour PyCharm, mais qui se traduit par ValueError: attempted relative import beyond top-level packageet MyPy Cannot find module named '.sibling_pkg.nephew'(notez un seul "." Dans l'erreur, pas deux). Pourtant, from sibling_pkg.nephew import my_functionfonctionne comme prévu, n'a pas d'erreur MyPy, mais entraîne une erreur PyCharm.
ubiquibacon
86

J'ai le même problème que vous. Je pense que le problème est que vous avez utilisé l'importation relative dans in-package import. Il n'y __init__.pyen a pas dans votre répertoire. Il suffit donc d'importer comme Moïse a répondu ci-dessus.

Le problème principal, je pense, est lorsque vous importez avec un point:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

Il équivaut à:

from __main__.p_02_paying_debt_off_in_a_year import compute_balance_after

__main__fait référence à votre module actuel p_03_using_bisection_search.py.


En bref, l'interpréteur ne connaît pas votre architecture d'annuaire.

Lorsque l'interprète entre p_03.py, le script est égal à:

from p_03_using_bisection_search.p_02_paying_debt_off_in_a_year import compute_balance_after

et p_03_using_bisection_searchne contient aucun module ou instance appelé p_02_paying_debt_off_in_a_year.


J'ai donc trouvé une solution plus propre sans changer les objets de valeur de l'environnement python (après avoir recherché comment les demandes fonctionnent dans l'importation relative):

L'architecture principale du répertoire est:

main.py

setup.py

---problem_set_02/

------__init__.py

------p01.py

------p02.py

------p03.py

Écrivez ensuite __init__.py:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

Ici __main__est __init__, il fait référence exactement au module problem_set_02.

Allez ensuite à main.py:

import problem_set_02

Vous pouvez également écrire un setup.pypour ajouter un module spécifique à l'environnement.

hcnhcn012
la source
9

Essayez de l'exécuter en tant que:

python3 -m p_03_using_bisection_search

Dan Keder
la source
2

Si vous avez créé un répertoire et un sous-répertoire, suivez les étapes ci-dessous et n'oubliez pas que tous les répertoires doivent avoir __init__.pypour être reconnus comme répertoire.

  1. Dans votre script, incluez import syset sys.path, vous pourrez voir tous les chemins disponibles pour Python. Vous devez pouvoir voir votre répertoire de travail actuel.

  2. Maintenant, importez le sous-répertoire et le module respectif que vous souhaitez utiliser en utilisant: import subdir.subdir.modulename as abcet maintenant vous pouvez utiliser les méthodes de ce module.

entrez la description de l'image ici

À titre d'exemple, vous pouvez voir dans cette capture d'écran que j'ai un répertoire parent et deux sous-répertoires et sous les deuxièmes sous-répertoires j'ai le module CommonFunction. À droite, ma console montre qu'après l'exécution de sys.path, je peux voir mon répertoire de travail.

Gaurav Singh
la source
1

Supprimez le point et importez absolue_import au début de votre fichier

from __future__ import absolute_import

from p_02_paying_debt_off_in_a_year import compute_balance_after
Aminah Nuraini
la source
1

Utilisez simplement le nom du dossier principal dans lequel se trouve le fichier .py.

from problem_set_02.p_02_paying_debt_off_in_a_year import compute_balance_after
FanBek
la source