ModuleNotFoundError: มันหมายความว่าอะไร __main__ ไม่ใช่แพ็คเกจ?


208

ฉันพยายามเรียกใช้โมดูลจากคอนโซล โครงสร้างของไดเรกทอรีของฉันคือ:

ป้อนคำอธิบายรูปภาพที่นี่

ฉันพยายามเรียกใช้โมดูลp_03_using_bisection_search.pyจากproblem_set_02ไดเรกทอรีโดยใช้:

$ python3 p_03_using_bisection_search.py

รหัสภายใน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()

ฉันกำลังนำเข้าฟังก์ชั่นที่เป็นp_02_paying_debt_off_in_a_year.pyรหัส:

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

ฉันได้รับข้อผิดพลาดต่อไปนี้:

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

ฉันไม่รู้ว่าจะแก้ไขปัญหานี้อย่างไร ฉันลองเพิ่ม__init__.pyไฟล์แล้วแต่มันยังใช้งานไม่ได้


3
ไม่ใช่ปัญหาของคุณ แต่ฉันแค่อยากจะโยนมันออกไปนั่นeval(input...อาจไม่ใช่ความคิดที่ดี ฉันแค่แยกวิเคราะห์แทนที่จะเปิดโอกาสในการใช้รหัสโดยอำเภอใจ
Carcigenicate

2
ฉันจะเดิมพันeval(input(...บิตที่แนะนำโดย 2to3 วันนี้ฉันทำอย่างนั้นกับฉันแล้ว ดีใจที่ฉันไม่ทำตามคำแนะนำที่ทำให้ตาบอด
ckot

คำตอบ:


238

เพียงลบจุดสำหรับการนำเข้าที่เกี่ยวข้องและทำ:

from p_02_paying_debt_off_in_a_year import compute_balance_after

56
คุณแก้มัน ทำไมนำเข้าที่ไม่ได้ทำงานแม้ว่าฉันจะเพิ่ม__init__.py?
lmiguelvargasf

23
คำตอบที่ยอมรับไม่ได้สำหรับฉัน คุณสามารถขยายคำตอบได้โดยเพิ่มการตั้งค่าตัวอย่างแบบเรียบง่ายหรือไม่?
รานาศ

13
สิ่งนี้ใช้ได้กับฉัน (ภายในแพ็คเกจเช่นที่ว่าง__init__.pyในโฟลเดอร์เดียวกัน) แม้ว่า PyCharm ของฉัน (2018.2.4) จะทำเครื่องหมายสิ่งนี้ว่า "การอ้างอิงที่ไม่ได้รับการแก้ไข" และไม่สามารถเติมข้อมูลการนำเข้าได้โดยอัตโนมัติ
djvg

33
@djvg - เพื่อแก้ไข PyCharm คุณสามารถทำเครื่องหมายไดเรกทอรีรูทเป็นซอร์สรูทได้
Denis Yakovlev

12
การทำงานกับการนำเข้าของไพ ธ อนทำให้โกรธเคือง มันก็เหมือนกับ Python 3, PyCharm และ MyPy ต่างก็หัวเราะกันอย่างหนักกับค่าใช้จ่ายของพวกเรา เป็นวิธีที่from ..sibling_pkg.nephew import my_functionใช้ได้กับ PyCharm แต่ให้ผลลัพธ์ValueError: attempted relative import beyond top-level packageและ MyPy Cannot find module named '.sibling_pkg.nephew'(บันทึกข้อผิดพลาด "." ข้อเดียวไม่ใช่สองข้อ) กระนั้นfrom sibling_pkg.nephew import my_functionทำงานได้ตามที่คาดไว้ไม่มีข้อผิดพลาด MyPy แต่ส่งผลให้เกิดข้อผิดพลาด PyCharm
ubiquibacon

85

ฉันมีปัญหาเช่นเดียวกับที่คุณทำ in-package importผมคิดว่าปัญหาคือการที่คุณใช้ญาตินำเข้าใน ไม่มี__init__.pyอยู่ในไดเรกทอรีของคุณ ดังนั้นเพียงนำเข้าตามที่โมเสสตอบไว้ด้านบน

ปัญหาหลักที่ฉันคิดคือเมื่อคุณนำเข้าด้วยจุด:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

มันเทียบเท่ากับ:

from __main__.p_02_paying_debt_off_in_a_year import compute_balance_after

ที่หมายถึงโมดูลปัจจุบันของคุณ__main__p_03_using_bisection_search.py


สั้น ๆ ล่ามไม่รู้จักสถาปัตยกรรมไดเรกทอรีของคุณ

เมื่อล่ามp_03.pyเข้ามาสคริปต์จะเท่ากับ:

from p_03_using_bisection_search.p_02_paying_debt_off_in_a_year import compute_balance_after

และ p_03_using_bisection_searchไม่ได้มีโมดูลหรือกรณีใด ๆ p_02_paying_debt_off_in_a_yearที่เรียกว่า


ดังนั้นฉันจึงได้คำตอบที่สะอาดขึ้นโดยไม่เปลี่ยนค่าของสภาพแวดล้อมของงูใหญ่ (หลังจากค้นหาว่าคำขอทำอย่างไรในการนำเข้าแบบสัมพัทธ์):

สถาปัตยกรรมหลักของไดเรกทอรีคือ:

main.py

setup.py

---problem_set_02/

------__init__.py

------p01.py

------p02.py

------p03.py

จากนั้นเขียนใน__init__.py:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

นี่__main__คือ__init__มันหมายถึงโมดูลproblem_set_02มันตรงหมายถึงโมดูล

จากนั้นไปที่main.py:

import problem_set_02

คุณยังสามารถเขียน a setup.pyเพื่อเพิ่มโมดูลเฉพาะกับสภาพแวดล้อม



2

หากคุณสร้างไดเรกทอรีและไดเรกทอรีย่อยให้ทำตามขั้นตอนด้านล่างและโปรดจำไว้ว่าไดเรกทอรีทั้งหมดจะต้องได้ __init__.pyรับการยอมรับว่าเป็นไดเรกทอรี

  1. ในสคริปต์ของคุณรวมimport sysและsys.pathคุณจะสามารถเห็นเส้นทางทั้งหมดที่มีให้กับ Python คุณจะต้องสามารถดูไดเรกทอรีการทำงานปัจจุบันของคุณ

  2. ตอนนี้นำเข้าไดเรกทอรีย่อยและโมดูลที่เกี่ยวข้องที่คุณต้องการใช้โดยใช้: import subdir.subdir.modulename as abcและตอนนี้คุณสามารถใช้วิธีการในโมดูลนั้น

ป้อนคำอธิบายรูปภาพที่นี่

CommonFunctionตัวอย่างเช่นคุณสามารถเห็นในภาพหน้าจอนี้ฉันมีไดเรกทอรีแม่หนึ่งและสองไดเรกทอรีย่อยและภายใต้สองไดเรกทอรีย่อยฉันมีโมดูล ด้านขวาคอนโซลของฉันแสดงให้เห็นว่าหลังจากการดำเนินการของsys.pathฉันสามารถดูไดเรกทอรีการทำงานของฉัน


1

ลบจุดและนำเข้า absolute_import ในตอนต้นของไฟล์ของคุณ

from __future__ import absolute_import

from p_02_paying_debt_off_in_a_year import compute_balance_after

1

เพียงใช้ชื่อโฟลเดอร์หลักที่มีไฟล์. py

from problem_set_02.p_02_paying_debt_off_in_a_year import compute_balance_after
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.