จะเพิ่มโมดูล Python ใน syspath ได้อย่างไร


69

ฉันมีโครงสร้างไฟล์ดังนี้:

Folder
   Common
      foo1.py
   TestFolder
      foo2.py

ฉันต้องการที่จะนำเข้าในและfoo2.py foo1.pyฉันพยายาม แต่มันไม่ทำงานบน Ubuntu:

sys.path.append(os.path.abspath('../../'))
from Common import foo1.py

คุณมี__init__.pyไฟล์ในโฟลเดอร์ของคุณหรือไม่? นี่คือวิธีที่ python สร้างแพ็คเกจและอนุญาตให้คุณนำเข้าโมดูลจากแพ็คเกจนั้น guide.python-distribute.org/creation.html
Bryan

ฉันมีไฟล์ init.py ใน Common และใน TestFolder
284474

คุณจำเป็นต้องใช้มันในไดเรกทอรีโฟลเดอร์เช่นเดียวกับในโฟลเดอร์ย่อยถ้าคุณต้องการที่จะนำเข้า
ไบรอัน

นี้init .py ว่างเปล่า?
284474

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

คำตอบ:


115

python ค้นหาโมดูลของมันอย่างไร

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

โดยค่าเริ่มต้น Python จะค้นหาโมดูลและแพ็คเกจของ$PYTHONPATHมัน

ในการค้นหาว่ามีอะไรรวมอยู่ใน $ PYTHONPATH ให้เรียกใช้โค้ดต่อไปนี้ในไพ ธ อน (3):

import sys
print(sys.path)

วิธีเพิ่มไดเรกทอรี

เป็นครั้งคราว

จากภายในไฟล์ไพ ธ อนคุณสามารถเพิ่มพา ธ ไปยังพา ธ เริ่มต้นเป็นครั้งคราวโดยเพิ่มบรรทัดต่อไปนี้ในส่วนหัวของแอปพลิเคชันหรือสคริปต์ของไพ ธ อน:

import sys
sys.path.insert(0, "/path/to/your/package_or_module")

ตัวอย่างเช่น:

หากฉันมีโฟลเดอร์: /home/myname/pythonfilesและฉันต้องการนำเข้าไฟล์ที่module_1.pyอยู่ในไดเรกทอรีนั้นฉันจะเพิ่มส่วนนี้ลงในส่วนหัวของรหัสของฉัน:

import sys
sys.path.insert(0, "/home/myname/pythonfiles")

และฉันสามารถนำเข้าไฟล์module_1.pyโดย:

import module_1

เมื่อฉันสร้างแพ็คเกจและต้องการนำเข้าโมดูลจากแพ็คเกจฉันต้องสร้างโฟลเดอร์$PYTHONPATHที่มีโมดูลพร้อมด้วยไฟล์ (สามารถว่างเปล่า) ที่เรียกว่า__init__.py

ตัวอย่างเช่น:

นำเข้าจากแพคเกจ (โฟลเดอร์) เรียกว่าmy_packageใน/home/myname/pythonfilesเพิ่ม/home/myname/pythonfilesเส้นทางไปยังคุณ$PYTHONPATHเช่นในตัวอย่างที่ 1 และนำเข้าโมดูลที่เรียกว่าmodule_2.py(ในโฟลเดอร์แพคเกจ) เพียงกับ: `

from <packagename> import module_2

การเพิ่มไดเรกทอรีไปยัง$PYTHONPATHอย่างถาวร:

เพิ่มบรรทัดต่อไปนี้ใน~/.profileไฟล์ของคุณ

export PYTHONPATH=$PYTHONPATH:/path/you/want/to/add

ไดเรกทอรีย่อย

จากภายในแพ็คเกจจะไม่รวมไดเรกทอรีย่อยเช่นนั้น คุณต้อง "เชน" ไดเรกทอรี ในการนำเข้าโมดูลmodule_3.pyภายในโฟลเดอร์subfolderภายในโฟลเดอร์packagename:

import packagename.subfolder.module_3

เนื่องจากข้อเท็จจริงที่ว่าโฟลเดอร์ย่อยทั้งหมดในแพ็คเกจรวม__init__.pyไฟล์ของตนเอง

เมื่อโมดูลอยู่ในไดเรกทอรีเดียวกับสคริปต์หรือแอปพลิเคชัน

ไม่จำเป็นต้องแทรกพา ธ ไปยังโมดูลเมื่อมันอยู่ในไดเรกทอรีเดียวกับสคริปต์หรือแอปพลิเคชันมันถูกเพิ่มโดยอัตโนมัติ

ตัวอย่าง:

หากฉันมีโฟลเดอร์ที่มีscript.pyและmodule.pyฉันสามารถนำเข้าโมดูลโดย:

import module

ฉันอยากจะแนะนำให้อ่านpython.org/dev/peps/pep-0328โดยเฉพาะถ้าคุณกำลังกำหนดเป้าหมาย Python 3 (หรือวางแผนที่จะกำหนดเป้าหมายในอนาคต)
zaadeh

ทำไมprintenv PYTHONPATHไม่มีอะไร
Stevie G

1
sys.path.append("/path/to/your/package_or_module")ยังเพิ่มเส้นทางไปยังค่าเริ่มต้นและทำให้สับสนน้อยลง เมื่อเทียบกับsys.path.insert(0,...)สิ่งที่มี0เป็นอาร์กิวเมนต์แรก
Paul Rougieux

1
@PaulRougieux: ปัญหาเกี่ยวกับการต่อท้ายพา ธ คือโมดูลของคุณอาจมีอยู่ที่อื่นในพา ธ (เช่นไฟล์ .egg) และคุณจะเลือกโมดูลนั้นในเวอร์ชันของคุณแทนที่จะเป็นหนึ่งในไฟล์ของคุณ
snark

6

วิธีที่ถูกต้องในการใช้การนำเข้าแบบสัมพัทธ์คือ:

from ..Common import foo1

และคุณยังจำเป็นต้องมี__init__.pyในทุกโฟลเดอร์ของคุณ


1
ขอบคุณ. แต่ถ้าฉันมีโมดูลซึ่งเป็นสองโฟลเดอร์อัพฉันจะอิมพอร์ตได้อย่างไร จาก .... โฟลเดอร์ไม่ทำงาน
user284474

มันใช้งานได้ในระดับเดียวหรือไม่?
Sylvain Pineau

ด้วยระดับเดียวมันใช้งานได้
284474

ตกลงคุณช่วยตอบคำถามนี้หน่อยได้ไหม? สำหรับหลายระดับแม้ว่าคุณสามารถถามคำถามที่แตกต่างกัน แต่แรกลองดูที่คำถามนี้และคำตอบนี้สำหรับวิธีที่ดีที่สุดในการโทรหาโมดูลของคุณภายในแพ็คเกจ
Sylvain Pineau

สิ่งนี้เป็นจริงสำหรับ Python 2 หรือ Python 3 หรือไม่ หรือทั้งคู่?
alex

2

หมายเหตุ: คำตอบนี้ล้าสมัยสำหรับ python 3 รุ่นล่าสุด แต่อยู่ที่นี่สำหรับรุ่นก่อนหน้า สำหรับข้อมูลเพิ่มเติมอ่านความคิดเห็นและhttps://www.python.org/dev/peps/pep-0420/


เป็นหลักทุกโฟลเดอร์ที่มีรหัสหลามที่คุณต้องการเพิ่มลงใน syspath ต้องการไฟล์ __init__.py ไฟล์ __init__.py เหล่านี้สามารถว่างเปล่าได้


ตามที่ฉันเข้าใจแล้วนี่ไม่ใช่กรณีอีกต่อไปแล้วไดเรกทอรีจะกลายเป็น "เนมสเปซ"
Aaron Hall

@AaronHall แหล่งที่น่าสนใจ?
don.joey

1
ลองใช้สิ่งนี้เพื่อเป็นหลักฐาน: python -c "from pathlib import Path; Path('ns').mkdir(); Path('ns/mod.py').write_text('''print('mod.py')'''); import ns.mod; from shutil import rmtree; rmtree('ns')"นี่คือเอกสารที่เกี่ยวข้องบางอย่างPEP 420 ซึ่งอธิบายการเพิ่มความหมายของแพ็คเกจเนมสเปซ
Aaron Hall
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.