ModuleNotFoundError: cosa significa __main__ non è un pacchetto?


209

Sto cercando di eseguire un modulo dalla console. La struttura della mia directory è questa:

inserisci qui la descrizione dell'immagine

Sto cercando di eseguire il modulo p_03_using_bisection_search.py, dalla problem_set_02directory utilizzando:

$ python3 p_03_using_bisection_search.py

Il codice all'interno 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()

Sto importando una funzione in p_02_paying_debt_off_in_a_year.pycui il codice è:

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

Ricevo il seguente errore:

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

Non ho idea di come risolvere questo problema. Ho provato ad aggiungere un __init__.pyfile, ma non funziona ancora.


3
Non è un tuo problema, ma volevo solo buttarlo fuori: eval(input...probabilmente non è una grande idea. Lo analizzerei invece di aprire l'opportunità per l'esecuzione arbitraria di codice.
— Carcigenicato il

2
Scommetto che quel eval(input(...bit è stato suggerito da 2to3. L'ho fatto fare a me oggi. felice di non seguire i suoi suggerimenti ciechi
— ckot

Risposte:


241

Basta rimuovere il punto per l'importazione relativa ed eseguire:

from p_02_paying_debt_off_in_a_year import compute_balance_after

56
lo risolvi. Perché l'importazione relativa non funziona anche se aggiungo __init__.py?
— lmiguelvargasf,

23
La risposta accettata non funziona per me. Potresti eventualmente espandere la risposta aggiungendo un esempio di installazione minimalista?
— Pranasas,

13
Questo funziona per me (all'interno di un pacchetto, ovvero con un vuoto __init__.pynella stessa cartella), anche se il mio PyCharm (2018.2.4) lo contrassegna come "riferimento non risolto" e non completa automaticamente l'importazione.
— djvg,

33
@djvg - Per correggere PyCharm puoi contrassegnare la directory root come root di origine
— Denis Yakovlev

12
Lavorare con le importazioni di Python è esasperante. È come se Python 3, PyCharm e MyPy stessero ridendo tutti a nostre spese. Come è from ..sibling_pkg.nephew import my_functionvalido per PyCharm, ma risulta in ValueError: attempted relative import beyond top-level packagee MyPy Cannot find module named '.sibling_pkg.nephew'(notare un singolo "." Nell'errore , non due). Tuttavia, from sibling_pkg.nephew import my_functionfunziona come previsto, non presenta un errore MyPy, ma provoca un errore PyCharm.
— ubiquibacon,

86

Ho lo stesso problema che hai fatto tu. Penso che il problema sia che hai usato l'importazione relativa in in-package import. Non ce n'è __init__.pynella tua directory. Quindi importa solo come Mosè ha risposto sopra.

Il problema principale che penso è quando si importa con un punto:

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

dove si __main__riferisce al modulo corrente p_03_using_bisection_search.py.


In breve, l'interprete non conosce l'architettura della directory.

Quando arriva l'interprete p_03.py, lo script è uguale a:

from p_03_using_bisection_search.p_02_paying_debt_off_in_a_year import compute_balance_after

e p_03_using_bisection_searchnon contiene alcun modulo o istanza chiamata p_02_paying_debt_off_in_a_year.


Quindi ho trovato una soluzione più pulita senza cambiare gli oggetti di valore dell'ambiente Python (dopo aver cercato come fanno le richieste nella relativa importazione):

L'architettura principale della directory è:

main.py

setup.py

---problem_set_02/

------__init__.py

------p01.py

------p02.py

------p03.py

Quindi scrivere in __init__.py:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

Qui __main__è __init__, si riferisce esattamente al modulo problem_set_02.

Quindi vai a main.py:

import problem_set_02

Puoi anche scrivere a setup.pyper aggiungere un modulo specifico all'ambiente.


9

Prova a eseguirlo come:

python3 -m p_03_using_bisection_search


2

Se hai creato una directory e una sottodirectory, segui i passaggi seguenti e tieni presente che tutte le directory devono essere __init__.pyriconosciute come directory.

  1. Nel tuo script, includi import syse sys.path, sarai in grado di vedere tutti i percorsi disponibili per Python. Devi essere in grado di vedere la tua directory di lavoro corrente.

  2. Ora importa la sottodirectory e il rispettivo modulo che vuoi usare usando: import subdir.subdir.modulename as abce ora puoi usare i metodi in quel modulo.

inserisci qui la descrizione dell'immagine

Ad esempio, puoi vedere in questa schermata che ho una directory principale e due sottodirectory e sotto le seconde sottodirectory ho il modulo CommonFunction. Sulla destra la mia console mostra che dopo l'esecuzione di sys.path, posso vedere la mia directory di lavoro.


1

Rimuovere il punto e importare absolute_import all'inizio del file

from __future__ import absolute_import

from p_02_paying_debt_off_in_a_year import compute_balance_after

1

Usa semplicemente il nome della cartella principale in cui si trova il file .py.

from problem_set_02.p_02_paying_debt_off_in_a_year import compute_balance_after
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.