นำเข้าโมดูลจากโฟลเดอร์ย่อย


104

ฉันต้องการนำเข้าโฟลเดอร์ย่อยเป็นโมดูล ดังนั้นทุกโฟลเดอร์ย่อยจะมีไฟล์__init__.py. โครงสร้างโฟลเดอร์ของฉันเป็นแบบนี้:

src\
  main.py
  dirFoo\
    __init__.py
    foofactory.py
    dirFoo1\
      __init__.py
      foo1.py
    dirFoo2\
      __init__.py
      foo2.py

ในสคริปต์หลักของฉันฉันนำเข้า

from dirFoo.foofactory import FooFactory

ในไฟล์โรงงานนี้ฉันรวมโมดูลย่อย:

from dirFoo1.foo1 import Foo1
from dirFoo2.foo2 import Foo2

ถ้าฉันเรียก foofactory ของฉันฉันได้รับข้อผิดพลาด python นั้นไม่สามารถนำเข้าโมดูลย่อย foo1 และ foo2:

Traceback (most recent call last):
  File "/Users/tmp/src/main.py", line 1, in <module>
from dirFoo.foofactory import FooFactory
  File "/Users/tmp/src/dirFoo/foofactory.py", line 1, in    <module>
from dirFoo1.foo1 import Foo1
    ImportError: No module named dirFoo1.foo1

คำตอบ:


137

ไม่จำเป็นต้องยุ่งกับคุณPYTHONPATHหรือsys.pathที่นี่

ในการใช้การนำเข้าแบบสัมบูรณ์ในแพ็คเกจอย่างถูกต้องคุณควรรวมชื่อแพ็กเกจ "root" ไว้ด้วยเช่น:

from dirFoo.dirFoo1.foo1 import Foo1
from dirFoo.dirFoo2.foo2 import Foo2

หรือคุณสามารถใช้การนำเข้าแบบสัมพัทธ์ :

from .dirfoo1.foo1 import Foo1
from .dirfoo2.foo2 import Foo2

47
สิ่งหนึ่งที่ต้องจำ! เพิ่มลง__init__.pyในทุกโฟลเดอร์ย่อยที่คุณกำลังนำเข้า
Aziz Alto

6
ว่างเปล่า__init__.pyอาจทำหน้าที่ได้
cerebrou

1
อะไรไวยากรณ์จะถ้าก่อนหน้านี้อยู่ในไดเรกทอรีแม่และรหัสบางอย่างเช่นFoo1 from Foo1 import *มีวิธีการเพื่อให้บรรลุผลเช่นเดียวกับที่เพื่อให้คุณไม่จำเป็นต้องทุกอย่างคำนำหน้าด้วยFoo1?
jxramos

1
@AzizAlto: หากไม่มีความคิดเห็นของคุณวิธีนี้ก็ไม่มีประโยชน์มากนัก
Alex

21

เพียงแจ้งที่นี่ (จาก newbee, keviv22)

อย่าใช้เพื่อประโยชน์ของคุณเองตั้งชื่อโฟลเดอร์หรือไฟล์ด้วยสัญลักษณ์เช่น "-" หรือ "_" หากคุณทำเช่นนั้นคุณอาจประสบปัญหาเล็กน้อย เช่นเดียวกับของฉันพูดว่าแม้ว่าคำสั่งการนำเข้าของคุณจะถูกต้อง แต่คุณจะไม่สามารถนำเข้าไฟล์ที่ต้องการซึ่งมีอยู่ในโฟลเดอร์ที่มีชื่อดังกล่าวได้สำเร็จ

การตั้งชื่อโฟลเดอร์ไม่ถูกต้องดังนี้:

  • Generic-Classes-Folder
  • Generic_Classes_Folder

การตั้งชื่อโฟลเดอร์ที่ถูกต้องสำหรับด้านบน:

  • GenericClassesFolder หรือ Genericclassesfolder หรือ genericClassesFolder (หรือเช่นนี้โดยไม่มีช่องว่างหรือสัญลักษณ์พิเศษระหว่างคำ)

ฉันทำผิดอะไร:

พิจารณาโครงสร้างไฟล์

Parent
   . __init__.py
   . Setup
     .. __init__.py
     .. Generic-Class-Folder
        ... __init__.py
        ... targetClass.py
   . Check
     .. __init__.py
     .. testFile.py

ฉันอยากทำอะไร?

  • จาก testFile.py ฉันต้องการนำเข้าไฟล์ 'targetClass.py' ภายในไฟล์ Generic-Class-Folder เพื่อใช้ฟังก์ชันชื่อ "functionExecute" ในไฟล์ 'targetClass.py'

ฉันสั่งอะไร

  • จาก 'testFile.py' เขียนคำสั่ง from Core.Generic-Class-Folder.targetClass import functionExecute
  • มีข้อผิดพลาดเช่น SyntaxError: invalid syntax

พยายามค้นหาหลายครั้งและดูคำถาม stackoverflow จำนวนมากและไม่สามารถตัดสินใจได้ว่าเกิดอะไรขึ้น ฉันตรวจสอบไฟล์ของฉันหลายครั้งฉันใช้__init__.pyไฟล์แทรกเส้นทางสภาพแวดล้อมและกังวลอย่างมากว่าเกิดอะไรขึ้น ......

และหลังจากนั้นไม่นานฉันก็คิดเรื่องนี้ได้ในขณะที่คุยกับเพื่อนของฉัน ฉันโง่เล็กน้อยที่ใช้หลักการตั้งชื่อแบบนี้ ฉันไม่ควรใช้ช่องว่างหรือสัญลักษณ์พิเศษเพื่อกำหนดชื่อสำหรับโฟลเดอร์หรือไฟล์ใด ๆ นี่คือสิ่งที่ฉันต้องการจะสื่อ มีวันที่ดี!

(ขออภัยสำหรับโพสต์ขนาดใหญ่ในช่วงนี้ ... เพียงแค่ปล่อยให้ความผิดหวังของฉันไป .... :) ขอบคุณ!)


22
การเว้นวรรคและขีดกลาง ("-") จะทำให้เกิดสิ่งนี้ แต่ขีดล่าง ("_") ยังคงใช้งานได้ดี
cowlinator

6

ตั้งค่าตัวแปรสภาพแวดล้อม PYTHONPATH ของคุณ ตัวอย่างเช่น PYTHONPATH =.: .. (สำหรับ * nix family)

นอกจากนี้คุณสามารถเพิ่มไดเร็กทอรีปัจจุบันของคุณด้วยตนเอง (src ในกรณีของคุณ) ไปยัง pythonpath:

import os
import sys
sys.path.insert(0, os.getcwd())

2

สมมติว่าโครงการของคุณมีโครงสร้างในลักษณะนี้:

+---MyPythonProject
|   +---.gitignore
|   +---run.py
|   |   +---subscripts
|   |   |   +---script_one.py
|   |   |   +---script_two.py

ภายในrun.pyคุณสามารถนำเข้าสคริปต์หนึ่งและสองโดย:

from subscripts import script_one as One
from subscripts import script_two as Two

ตอนนี้ยังอยู่ข้างในrun.pyคุณจะสามารถเรียกวิธีการของพวกเขาด้วย:

One.method_from_one(param)
Two.method_from_two(other_param)

1

เพียงสร้างไฟล์ ___init____.py ว่างและเพิ่มในรูทรวมถึงไดเร็กทอรีย่อย / โฟลเดอร์ทั้งหมดของแอปพลิเคชัน python ที่คุณมีโมดูล python อื่น ๆ


-2

มีปัญหาแม้ว่าจะมีinit. py อยู่ในโฟลเดอร์ย่อยและสิ่งที่ขาดหายไปคือการเพิ่ม "เป็น" หลังจากนำเข้า

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