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.