ModuleNotFoundError: Apa artinya __main__ bukan paket?

209

Saya mencoba menjalankan modul dari konsol. Struktur direktori saya adalah ini:

masukkan deskripsi gambar di sini

Saya mencoba menjalankan modul p_03_using_bisection_search.py, dari problem_set_02direktori menggunakan:

$ python3 p_03_using_bisection_search.py

Kode di dalamnya p_03_using_bisection_search.pyadalah:

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

Saya mengimpor fungsi yang memiliki p_02_paying_debt_off_in_a_year.pykode:

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

Saya mendapatkan kesalahan berikut:

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

Saya tidak tahu bagaimana menyelesaikan masalah ini. Saya sudah mencoba menambahkan __init__.pyfile, tetapi masih belum berfungsi.

lmiguelvargasf
sumber
3
Bukan masalah Anda, tapi saya hanya ingin membuangnya di sana: eval(input...mungkin bukan ide yang bagus. Saya hanya menguraikannya alih-alih membuka peluang untuk eksekusi kode arbitrer.
Carcigenicate
2
Saya berani bertaruh bahwa eval(input(...bit disarankan oleh 2to3. Saya telah melakukannya untuk saya hari ini. senang saya tidak mengikuti saran itu blindling
ckot

Jawaban:

240

Cukup hapus titik untuk impor relatif dan lakukan:

from p_02_paying_debt_off_in_a_year import compute_balance_after
Moses Koledoye
sumber
56
kamu menyelesaikannya. Mengapa impor relatif tidak berfungsi meskipun saya menambahkan __init__.py?
lmiguelvargasf
23
Jawaban yang diterima tidak berfungsi untuk saya. Bisakah Anda memperluas jawabannya dengan menambahkan contoh pengaturan minimalis?
Pranasas
13
Ini berfungsi untuk saya (di dalam paket, yaitu dengan kosong __init__.pydi folder yang sama), meskipun PyCharm saya (2018.2.4) menandai ini sebagai "referensi yang belum terselesaikan" dan gagal melengkapi impor secara otomatis.
djvg
33
@djvg - Untuk memperbaiki PyCharm, Anda dapat menandai direktori root sebagai sumber root
Denis Yakovlev
12
Bekerja dengan impor Python sangat menyebalkan. Ini seperti Python 3, PyCharm, dan MyPy semua tertawa keras atas biaya kami. Bagaimana ini from ..sibling_pkg.nephew import my_functionberlaku untuk PyCharm, tetapi menghasilkan ValueError: attempted relative import beyond top-level packagedan MyPy Cannot find module named '.sibling_pkg.nephew'(catat satu "." Dalam kesalahan, bukan dua). Namun, from sibling_pkg.nephew import my_functionberfungsi sebagaimana dimaksud, tidak memiliki kesalahan MyPy, tetapi menghasilkan kesalahan PyCharm.
ubiquibacon
86

Saya memiliki masalah yang sama seperti Anda. Saya pikir masalahnya adalah Anda menggunakan impor relatif in-package import. Tidak ada __init__.pydi direktori Anda. Jadi impor saja seperti yang dijawab Musa di atas.

Masalah inti yang saya pikir adalah ketika Anda mengimpor dengan sebuah titik:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

Itu sama dengan:

from __main__.p_02_paying_debt_off_in_a_year import compute_balance_after

di mana __main__mengacu pada modul Anda saat ini p_03_using_bisection_search.py.


Secara singkat, penerjemah tidak tahu arsitektur direktori Anda.

Ketika penerjemah masuk p_03.py, skrip sama dengan:

from p_03_using_bisection_search.p_02_paying_debt_off_in_a_year import compute_balance_after

dan p_03_using_bisection_searchtidak mengandung modul atau instance yang dipanggil p_02_paying_debt_off_in_a_year.


Jadi saya datang dengan solusi bersih tanpa mengubah barang berharga lingkungan python (setelah mencari bagaimana permintaan dilakukan dalam impor relatif):

Arsitektur utama direktori adalah:

main.py

setup.py

---problem_set_02/

------__init__.py

------p01.py

------p02.py

------p03.py

Kemudian tulis __init__.py:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

Ini __main__dia __init__, tepatnya mengacu pada modul problem_set_02.

Lalu pergi ke main.py:

import problem_set_02

Anda juga dapat menulis a setup.pyuntuk menambahkan modul khusus ke lingkungan.

hcnhcn012
sumber
9

Coba jalankan sebagai:

python3 -m p_03_using_bisection_search

Dan Keder
sumber
2

Jika Anda telah membuat direktori dan sub-direktori, ikuti langkah-langkah di bawah ini dan harap diingat bahwa semua direktori harus __init__.pymembuatnya dikenal sebagai direktori.

  1. Dalam skrip Anda, sertakan import sysdan sys.path, Anda akan dapat melihat semua jalur yang tersedia untuk Python. Anda harus dapat melihat direktori kerja Anda saat ini.

  2. Sekarang impor sub-direktori dan modul masing-masing yang ingin Anda gunakan menggunakan: import subdir.subdir.modulename as abcdan sekarang Anda dapat menggunakan metode dalam modul itu.

masukkan deskripsi gambar di sini

Sebagai contoh, Anda dapat melihat di screenshot ini saya memiliki satu direktori induk dan dua sub-direktori dan di bawah sub-direktori kedua saya memiliki modul CommonFunction. Di sebelah kanan konsol saya menunjukkan bahwa setelah eksekusi sys.path, saya dapat melihat direktori kerja saya.

Gaurav Singh
sumber
1

Hapus titik dan impor absolute_import di awal file Anda

from __future__ import absolute_import

from p_02_paying_debt_off_in_a_year import compute_balance_after
Aminah Nuraini
sumber
1

Cukup gunakan nama folder utama tempat file .py berada.

from problem_set_02.p_02_paying_debt_off_in_a_year import compute_balance_after
FanBek
sumber