การนำเข้าไฟล์จากโฟลเดอร์อื่น


1403

ฉันมีโครงสร้างโฟลเดอร์ต่อไปนี้

application/app/folder/file.py

และฉันต้องการนำเข้าฟังก์ชั่นบางอย่างจากfile.pyในไฟล์ Python อื่นที่อยู่ในนั้น

application/app2/some_folder/some_file.py

ฉันได้พยายาม

from application.app.folder.file import func_name

และความพยายามอื่น ๆ ที่หลากหลาย แต่จนถึงขณะนี้ฉันไม่สามารถนำเข้าได้อย่างถูกต้อง ฉันจะทำสิ่งนี้ได้อย่างไร


2
ที่เกี่ยวข้อง: stackoverflow.com/q/43476403/674039
Wim

การอ่านเอกสารอย่างเป็นทางการช่วยฉันได้มาก! docs.python.org/3/reference/ ......
Kavin Raju S

คำตอบ:


1439

คุณไม่สามารถทำได้ เมื่อนำเข้าไฟล์ Python จะค้นหาเฉพาะไดเรกทอรีปัจจุบันไดเรกทอรีที่สคริปต์จุดเริ่มต้นใช้งานsys.pathซึ่งรวมถึงสถานที่ต่างๆเช่นไดเรกทอรีการติดตั้งแพ็คเกจ (จริงๆแล้วมันซับซ้อนกว่านี้เล็กน้อย แต่ครอบคลุมกรณีส่วนใหญ่) .

อย่างไรก็ตามคุณสามารถเพิ่มเส้นทาง Python ในขณะใช้งานจริง:

# some_file.py
import sys
# insert at 1, 0 is the script path (or '' in REPL)
sys.path.insert(1, '/path/to/application/app/folder')

import file

355
sys.path.append('/path/to/application/app/folder')is imo สะอาดกว่า
pseudosudo

387
@ pseudosudo: ใช่มันเป็น แต่การแทรกไว้ที่จุดเริ่มต้นมีประโยชน์ในการรับประกันว่าเส้นทางจะถูกค้นหาก่อนที่คนอื่น ๆ (แม้ในตัว) ในกรณีของการตั้งชื่อความขัดแย้ง
คาเมรอน

8
@kreativitea - sys.pathส่งคืน a listไม่ใช่dequeและมันก็โง่ที่จะแปลงlista dequeและ back
ArtOfWarfare

37
มันถือเป็นวิธี pythonic ในการจัดการไฟล์. py ในโฟลเดอร์หรือไม่? ฉันสงสัยว่า ... ทำไมจึงไม่รองรับค่าเริ่มต้น มันไม่สมเหตุสมผลเลยที่จะดูแลไฟล์. py ทั้งหมดในไดเรกทอรีเดียว ..
Ofir

49
@Ofir: ไม่นี่ไม่ใช่วิธีการทำความสะอาดแบบไพทอนที่ดี โดยทั่วไปคุณควรใช้แพคเกจ (ซึ่งจะขึ้นอยู่กับต้นไม้ไดเรกทอรี) คำตอบนี้เฉพาะเจาะจงกับคำถามที่ถามและด้วยเหตุผลบางประการทำให้มีจำนวนผู้โหวตมากขึ้น
คาเมรอน

709

ไม่มีอะไรผิดปกติกับ:

from application.app.folder.file import func_name

เพียงตรวจสอบให้แน่ใจว่าfolderมีคำสั่งนี้ด้วย__init__.pyซึ่งจะช่วยให้สามารถรวมเป็นแพ็คเกจได้ ไม่แน่ใจว่าทำไมคำตอบอื่น ๆ PYTHONPATHพูดคุยเกี่ยวกับ


47
เนื่องจากไม่ครอบคลุมถึงกรณีที่PYTHONPATHจำเป็นต้องแก้ไข สมมติว่าคุณมีสองโฟลเดอร์ในระดับเดียวกัน: และA มี ลองนำเข้าอะไรบางอย่างจากภายใน BA__init.py__BA
msvalkon

32
ภายในinit.pyหรือ__init__.pyไฟล์คืออะไร
Lorem Ipsum Dolor

47
@Xinyang มันอาจเป็นไฟล์ว่างเปล่า มันมีอยู่มากบอก Python ให้ถือว่าไดเรกทอรีเป็นแพ็คเกจ
jay

9
แน่นอนคำตอบนี้อนุมานว่าapplicationและappแพคเกจแล้ว (เช่นคุณมีอยู่แล้ว__init__.pyทั้งในส่วนของพวกเขา) เป็นผลมาจากการเพิ่ม__init__.pyยังfolder, application.app.folderกลายเป็น (ย่อย) แพคเกจจากการที่คุณสามารถเข้าถึงโมดูล application.app.folder.fileที่มีสัญลักษณ์func_nameนี้สามารถนำเข้า
Yibo ยาง

30
ไม่ว่าฉันจะพยายามอะไรมันก็ใช้ไม่ได้ ฉันต้องการนำเข้าจากไดเรกทอรี "พี่น้อง" ดังนั้นหนึ่งรายการขึ้นลง ทุกคนมี __ init __. py's รวมถึงผู้ปกครอง python 3 ตัวนี้หรือไม่?
dasWesen

109

เมื่อโมดูลอยู่ในตำแหน่งขนานเช่นเดียวกับคำถาม:

application/app2/some_folder/some_file.py
application/app2/another_folder/another_file.py

การจดชวเลขนี้ทำให้โมดูลหนึ่งมองเห็นได้ในอีกโมดูล:

import sys
sys.path.append('../')

24
เป็นข้อแม้: วิธีนี้ใช้ได้ตราบใดที่สคริปต์การอิมพอร์ตถูกรันจากไดเร็กทอรีที่มี ไม่เช่นนั้นพาเรนต์ไดเร็กทอรีของไดเร็กทอรีอื่นใดที่สคริปต์รันจะถูกผนวกเข้ากับพา ธ และการอิมพอร์ตจะล้มเหลว
Carl Smith

14
เพื่อหลีกเลี่ยงปัญหานี้เราสามารถรับพาเรนต์ของไฟล์ได้sys.path.append(os.path.dirname(os.path.abspath(__file__)))
Rahul

นั่นไม่ได้ผลสำหรับฉัน - ฉันต้องเพิ่มชื่อเพิ่มเติมในนั้นเพื่อไต่กลับขึ้นไปยังผู้ปกครองเพื่อให้การเรียกใช้cli/foo.pyจากบรรทัดคำสั่งสามารถทำได้import cli.bar
RCross

2
@Rahul โซลูชันของคุณใช้ไม่ได้กับเชลล์แบบโต้ตอบ
towi_parallelism

ถ้าคุณเรียกใช้จากโฟลเดอร์รากของคุณ (เช่น. โฟลเดอร์ที่ใช้งาน) คุณอาจจะดีกับแล้วนำเข้าโมดูลโดยใช้sys.path.append('.') from app2.some_folder.some_file import your_functionอีกวิธีหนึ่งที่ใช้งานได้สำหรับฉันกำลังทำงานpython3 -m app2.another_folder.another_fileจากโฟลเดอร์รูท
ติดยาเสพติด

68

นำเข้า sys ครั้งแรกใน name-file.py

 import sys

ลำดับที่สองผนวกเส้นทางโฟลเดอร์ใน name-file.py

sys.path.insert(0, '/the/folder/path/name-package/')

ที่สามสร้างไฟล์เปล่าชื่อ __ init __.py ในไดเรกทอรีย่อยของคุณ (นี่บอก Python ว่าเป็นแพ็คเกจ)

  • name-file.py
  • ชื่อแพคเกจ
    • __ init __.py
    • name-module.py

สี่นำเข้าโมดูลภายในโฟลเดอร์ใน name-file.py

from name-package import name-module

5
ด้วยชื่อโฟลเดอร์ที่อยู่ด้านล่าง name-file.py สิ่งนี้น่าจะใช้ได้แม้ไม่มีsys.path.insert-command ดังนั้นคำตอบจะเป็นคำถามถ้าโซลูชันนี้ใช้ได้แม้ว่าชื่อโฟลเดอร์จะอยู่ในตำแหน่งที่กำหนดเองก็ตาม
บาสเตียน

55

ฉันคิดว่าวิธีการเฉพาะกิจจะใช้ตัวแปรสภาพแวดล้อมPYTHONPATHตามที่อธิบายไว้ในเอกสารประกอบ: Python2 , Python3

# Linux & OSX
export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH

# Windows
set PYTHONPATH=C:\path\to\dirWithScripts\;%PYTHONPATH%

เดี๋ยวก่อนฉันจะแทนที่ myScripts ด้วยชื่อไฟล์หรือไม่
Vladimir Putin

4
ไม่ด้วยพา ธ ของไดเรกทอรีไปยังไฟล์. py ของคุณ
Ax3l

1
น่าเสียดายที่ถ้าคุณใช้แอนนาคอนดาสิ่งนี้จะไม่ทำงานเนื่องจาก PYTHONPATH นั้นไม่ได้ใช้ภายในจริงๆ!
information_interchange

สำหรับการเปลี่ยนแปลง (ล่าสุด) ในแอนาคอนดาดู SO นี้สำหรับเวิร์กโฟลว์และความคิดเห็นเกี่ยวกับการแก้ไข: stackoverflow.com/questions/17386880/…โดยทั่วไปแล้วให้สร้างและติดตั้งแพ็กเกจขนาดเล็กแทนการแฮ็ค dir นำเข้า
Ax3l

46

คำตอบที่นี่ขาดความชัดเจนนี่คือการทดสอบใน Python 3.6

ด้วยโครงสร้างโฟลเดอร์นี้:

main.py
|
---- myfolder/myfile.py

myfile.pyมีเนื้อหาอยู่ที่ไหน:

def myfunc():
    print('hello')

คำสั่งนำเข้าmain.pyคือ:

from myfolder.myfile import myfunc
myfunc()

และนี่จะพิมพ์สวัสดี


9
การเพิ่มไฟล์การกำหนดค่าinit .py (ว่าง) ใน myfolder ทำงานให้ฉันบน linux (y)
Vincent

7
@Vincent คุณหมายถึง__init__.pyอะไร
mrgloom

2
@mrgloom แน่นอน
Vincent

3
ด้วยเหตุผลบางอย่างการเพิ่ม__init__.pyไม่ทำงานสำหรับฉัน ฉันใช้ Py 3.6.5 บน Ubuntu 18. ใช้งานได้กับ Pycharm แต่ไม่ใช่จากเทอร์มินัล
Crearo Rotar

9
นี่ไม่เกี่ยวข้องกับคำถามที่ถามเกี่ยวกับการนำเข้าไฟล์จากสาขาที่แตกต่างกันของทรีไฟล์มากกว่าไดเรกทอรีทำงานปัจจุบัน
Alexander Rossa

44

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

ในการทำเช่นนี้คุณต้องเปลี่ยนแปลงสิ่งนี้:

from application.app.folder.file import func_name

สำหรับสิ่งนี้:

from .application.app.folder.file import func_name

โดยการเพิ่มจุดคุณกำลังบอกว่ามองหาในโฟลเดอร์นี้สำหรับโฟลเดอร์แอปพลิเคชันแทนที่จะมองในไดเรกทอรี Python


2
นี่คือสิ่งที่ฉันคงที่
พี

32

จากสิ่งที่ฉันรู้เพิ่ม__init__.pyไฟล์โดยตรงในโฟลเดอร์ของฟังก์ชั่นที่คุณต้องการนำเข้าจะทำงาน


7
เฉพาะในกรณีที่สคริปต์ที่ต้องการรวมไดเรกทอรีอื่นนั้นมีอยู่ใน sys.path แล้ว
Ax3l

2
ฉันใช้sys.path.append(tools_dir)บน Windows และฉันไม่จำเป็นต้องเพิ่ม__init__.py' file in my directory tools_dir`
herve-guerin

25

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

นี่คือตัวอย่าง ก่อนไฟล์ที่จะนำเข้าชื่อfoo.py:

def announce():
    print("Imported!")

รหัสที่นำเข้าไฟล์ด้านบนเป็นแรงบันดาลใจอย่างมากจากตัวอย่างในเอกสารประกอบ:

import importlib.util

def module_from_file(module_name, file_path):
    spec = importlib.util.spec_from_file_location(module_name, file_path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module

foo = module_from_file("foo", "/path/to/foo.py")

if __name__ == "__main__":
    print(foo)
    print(dir(foo))
    foo.announce()

ผลลัพธ์:

<module 'foo' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!

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

import importlib.util

def module_from_file(module_name, file_path):
    spec = importlib.util.spec_from_file_location(module_name, file_path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module

baz = module_from_file("bar", "/path/to/foo.py")

if __name__ == "__main__":
    print(baz)
    print(dir(baz))
    baz.announce()

ผลลัพธ์:

<module 'bar' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!

โมดูลการนำเข้าแบบโปรแกรมได้รับการแนะนำใน Python 3.1 และให้คุณควบคุมวิธีการนำเข้าโมดูล อ้างถึงเอกสารประกอบสำหรับข้อมูลเพิ่มเติม


11
ฉันไม่รู้ว่ามีใครพยายามเข้าใจสิ่งนี้หรือไม่ แต่ฉันคิดว่ามันซับซ้อนเกินไป
Dan

23

ทำงานให้ฉันใน python3 บน linux

import sys  
sys.path.append(pathToFolderContainingScripts)  
from scriptName import functionName #scriptName without .py extension  

6
sys.path.append("/home/linux/folder/")- อย่าใช้ทางลัดเช่น"~/folder/"
daGo

22

ลองนำเข้าที่เกี่ยวข้องของ Python:

from ...app.folder.file import func_name

ทุกจุดนำเป็นอีกระดับที่สูงขึ้นในลำดับชั้นเริ่มต้นด้วยไดเรกทอรีปัจจุบัน


ปัญหา? หากสิ่งนี้ไม่ได้ผลสำหรับคุณคุณอาจจะได้รับบิตจากการนำเข้าที่เกี่ยวข้องของ gotcha อ่านคำตอบและความคิดเห็นสำหรับรายละเอียดเพิ่มเติม: วิธีแก้ไข "พยายามนำเข้าที่เกี่ยวข้องในแพคเกจที่ไม่ใช่แพคเกจ" แม้จะมี __init__.py

คำแนะนำ: มี__init__.pyทุกระดับไดเรกทอรี คุณอาจต้องpython -m application.app2.some_folder.some_file(ออกจาก. py) ซึ่งคุณเรียกใช้จากไดเรกทอรีระดับบนสุดหรือมีไดเรกทอรีระดับบนสุดใน PYTHONPATH ของคุณ วุ้ย


22

ฉันเผชิญกับความท้าทายเดียวกันโดยเฉพาะเมื่อนำเข้าไฟล์หลายไฟล์นี่คือวิธีที่ฉันจัดการเพื่อเอาชนะมัน

import os, sys

from os.path import dirname, join, abspath
sys.path.insert(0, abspath(join(dirname(__file__), '..')))

from root_folder import file_name

2
คำตอบของคุณจะมีประโยชน์มากขึ้นถ้าคุณสามารถอธิบายสิ่งที่แตกต่างจากการนำเข้าแบบปกติ
not2qubit

1
ฉันมี /path/dir1/__init__.py และ /path/dir1/mod.py สำหรับ /path/some.py จาก dir1.mod import func ทำงาน เมื่ออยู่ใน /path/dir2/some.py มันจะทำงานหลังจากที่ฉันคัดลอกและวางคำตอบข้างต้นที่ด้านบนของไฟล์ ไม่ต้องการที่จะแก้ไขเส้นทางของฉันเพราะไม่ใช่ทุกโครงการของหลามที่ฉันมีอยู่ใน / path /
jwal

19

พิจารณาapplicationเป็นไดเรกทอรีรากสำหรับโครงการหลามของคุณสร้างที่ว่างเปล่า__init__.pyแฟ้มในapplication, appและfolderโฟลเดอร์ จากนั้นในsome_file.pyการเปลี่ยนแปลงของคุณดังต่อไปนี้เพื่อรับนิยามของ func_name:

import sys
sys.path.insert(0, r'/from/root/directory/application')

from application.app.folder.file import func_name ## You can also use '*' wildcard to import all the functions in file.py file.
func_name()

ควรเป็น: sys.path.insert (0, r '/ from / root / directory')
Bolaka

18

การใช้ sys.path.append กับพา ธ สัมบูรณ์ไม่เหมาะเมื่อย้ายแอ็พพลิเคชันไปยังสภาพแวดล้อมอื่น การใช้พา ธ สัมพัทธ์จะไม่ทำงานเสมอไปเนื่องจากไดเรกทอรีการทำงานปัจจุบันขึ้นอยู่กับวิธีการเรียกใช้สคริปต์

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

/home/me/application/app2/some_folder/vanilla.py
/home/me/application/app2/another_folder/mango.py

และสมมติว่าคุณต้องการนำเข้าโมดูล "มะม่วง" คุณสามารถทำสิ่งต่อไปนี้ใน vanilla.py:

import sys, os.path
mango_dir = (os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
+ '/another_folder/')
sys.path.append(mango_dir)
import mango

แน่นอนคุณไม่ต้องการตัวแปร mango_dir

หากต้องการทำความเข้าใจวิธีการใช้งานดูที่ตัวอย่างเซสชันแบบโต้ตอบนี้

>>> import os
>>> mydir = '/home/me/application/app2/some_folder'
>>> newdir = os.path.abspath(os.path.join(mydir, '..'))
>>> newdir
    '/home/me/application/app2'
>>> newdir = os.path.abspath(os.path.join(mydir, '..')) + '/another_folder'
>>> 
>>> newdir
'/home/me/application/app2/another_folder'
>>> 

และตรวจสอบเอกสารของos.path


13

สิ่งนี้ใช้ได้กับฉันบน windows

# some_file.py on mainApp/app2 
import sys
sys.path.insert(0, sys.path[0]+'\\app2')

import some_file

10

ฉันค่อนข้างพิเศษ: ฉันใช้ Python กับ Windows!

ฉันเพิ่งกรอกข้อมูล: สำหรับทั้ง Windows และ Linux ทั้งเส้นทางแบบสัมพันธ์และแบบสัมบูรณ์ทำงานได้sys.path(ฉันต้องการเส้นทางแบบสัมพัทธ์เพราะฉันใช้สคริปต์ของฉันบนพีซีหลายเครื่องและอยู่ในไดเรกทอรีหลักที่แตกต่างกัน)

และเมื่อใช้ Windows ทั้งคู่\และ/สามารถใช้เป็นตัวคั่นสำหรับชื่อไฟล์และแน่นอนว่าคุณต้องเพิ่ม\สตริง Python เป็นสองเท่า
ตัวอย่างที่ถูกต้อง:

sys.path.append('c:\\tools\\mydir')
sys.path.append('..\\mytools')
sys.path.append('c:/tools/mydir')
sys.path.append('../mytools')

(หมายเหตุ: ฉันคิดว่า/สะดวกกว่า\ถ้ามี 'Windows-native' น้อยกว่าเพราะใช้งานร่วมกับ Linux และเขียนและคัดลอกไปยัง Windows Explorer ได้ง่ายขึ้น)


4
os.path.join ('tools', 'mydir')
Corey Goldberg

7

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

ฉันทดสอบสิ่งนี้บน Linux แต่มันควรทำงานในระบบปฏิบัติการสมัยใหม่ที่รองรับการเชื่อมโยงสัญลักษณ์

ข้อดีอย่างหนึ่งของวิธีนี้คือคุณสามารถชี้ไปที่โมดูลที่อยู่ในสำเนาการทำงานของสาขา SVC ในพื้นที่ของคุณซึ่งสามารถลดความซับซ้อนของรอบการพัฒนาและลดโหมดความล้มเหลวในการจัดการโมดูลรุ่นต่างๆ


7

ในกรณีของฉันฉันมีชั้นเรียนที่จะนำเข้า ไฟล์ของฉันดูเหมือนว่านี้:

# /opt/path/to/code/log_helper.py
class LogHelper:
    # stuff here

ในไฟล์หลักของฉันฉันรวมรหัสผ่าน:

import sys
sys.path.append("/opt/path/to/code/")
from log_helper import LogHelper

1
@ not2qubit sys ไม่ได้รับการนำเข้าในคำตอบ
วอลเตอร์

7

ฉันชนคำถามเดียวกันหลายครั้งดังนั้นฉันต้องการแบ่งปันวิธีแก้ปัญหาของฉัน

Python เวอร์ชั่น: 3.X

โซลูชันต่อไปนี้สำหรับผู้ที่พัฒนาแอปพลิเคชันของคุณใน Python เวอร์ชัน 3.X เนื่องจากPython 2 ไม่รองรับตั้งแต่ Jan / 1/2020ม.ค.

โครงสร้างโครงการ

ในหลาม 3 คุณไม่จำเป็นต้อง__init__.pyอยู่ในไดเรกทอรีย่อยของโครงการอันเนื่องมาจากแพคเกจ Namespace โดยปริยาย ดูIs init .py ไม่จำเป็นสำหรับแพ็คเกจใน Python 3.3+

Project 
├── main.py
├── .gitignore
|
├── a
|   └── file_a.py
|
└── b
    └── file_b.py

คำชี้แจงปัญหา

ในfile_b.pyฉันต้องการที่จะนำเข้าชั้นเรียนAในfile_a.pyภายใต้โฟลเดอร์

โซลูชั่น

# 1 วิธีที่รวดเร็ว แต่สกปรก

โดยไม่ต้องติดตั้งแพคเกจเหมือนคุณกำลังพัฒนาโครงการใหม่

ใช้try catchเพื่อตรวจสอบว่าข้อผิดพลาด ตัวอย่างรหัส:

import sys
try:
    # The insertion index should be 1 because index 0 is this file
    sys.path.insert(1, '/absolute/path/to/folder/a')  # the type of path is string
    # because the system path already have the absolute path to folder a
    # so it can recognize file_a.py while searching 
    from file_a import A
except (ModuleNotFoundError, ImportError) as e:
    print("{} fileure".format(type(e)))
else:
    print("Import succeeded")

# 2 ติดตั้งแพคเกจของคุณ

เมื่อคุณติดตั้งแอปพลิเคชันของคุณ (ในโพสต์นี้จะไม่รวมบทแนะนำการติดตั้ง)

คุณทำได้ง่ายๆ

try:
    from __future__ import absolute_import
    # now it can reach class A of file_a.py in folder a 
    # by relative import
    from ..a.file_a import A  
except (ModuleNotFoundError, ImportError) as e:
    print("{} fileure".format(type(e)))
else:
    print("Import succeeded")

การเข้ารหัสที่มีความสุข!


สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการนำเข้าแบบสัมบูรณ์
WY Hsu

3

ฉันกำลังทำงานในโครงการaที่ฉันต้องการให้ผู้ใช้ติดตั้งผ่านทางpip install aด้วยรายการไฟล์ต่อไปนี้:

.
├── setup.py
├── MANIFEST.in
└── a
    ├── __init__.py
    ├── a.py
    └── b
        ├── __init__.py
        └── b.py

setup.py

from setuptools import setup

setup (
  name='a',
  version='0.0.1',
  packages=['a'],
  package_data={
    'a': ['b/*'],
  },
)

MANIFEST.in

recursive-include b *.*

a / init .py

from __future__ import absolute_import

from a.a import cats
import a.b

A / a.py

cats = 0

a / b / init .py

from __future__ import absolute_import

from a.b.b import dogs

A / B / b.py

dogs = 1

ฉันติดตั้งโมดูลโดยเรียกใช้สิ่งต่อไปนี้จากไดเรกทอรีด้วยMANIFEST.in:

python setup.py install

จากนั้นในตำแหน่งที่แตกต่างกันโดยสิ้นเชิงในระบบไฟล์ของ/moustache/armwrestleฉันฉันสามารถเรียกใช้:

import a
dir(a)

ซึ่งยืนยันว่าa.catsเท่ากับ 0 a.b.dogsจริงและเท่ากับ 1 ตามที่ตั้งใจไว้



1

คุณสามารถรีเฟรชเชลล์ Python ได้โดยกด f5 หรือไปที่ Run-> Run Module วิธีนี้คุณไม่จำเป็นต้องเปลี่ยนไดเรกทอรีเพื่ออ่านข้อมูลจากไฟล์ Python จะเปลี่ยนไดเรกทอรีโดยอัตโนมัติ แต่ถ้าคุณต้องการทำงานกับไฟล์ต่าง ๆ จากสารบบที่แตกต่างกันใน Python Shell คุณสามารถเปลี่ยนไดเรคทอรี่เป็น sys ได้ตามที่คาเมรอนกล่าวก่อนหน้านี้


1

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


1

คุณสามารถใช้ importlib เพื่อนำเข้าโมดูลที่คุณต้องการนำเข้าโมดูลจากโฟลเดอร์โดยใช้สตริงดังนี้:

import importlib

scriptName = 'Snake'

script = importlib.import_module('Scripts\\.%s' % scriptName)

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

script.Hello()

ฉันได้ทดสอบสิ่งนี้ใน Python 3.6 แล้ว


0

ฉันเคยมีปัญหาเหล่านี้หลายครั้ง ฉันมาที่หน้าเดียวกันนี้มาก ในปัญหาสุดท้ายของฉันฉันต้องเรียกใช้serverจากไดเรกทอรีคงที่ แต่เมื่อใดก็ตามที่การดีบักฉันต้องการเรียกใช้จากไดเรกทอรีย่อยที่แตกต่างกัน

import sys
sys.insert(1, /path) 

ไม่ไม่ทำงานสำหรับฉันเพราะในโมดูลที่แตกต่างกันผมต้องอ่านที่แตกต่างกัน* .csvไฟล์ที่มีทั้งหมดในไดเรกทอรีเดียวกัน

ในท้ายที่สุดสิ่งที่ได้ผลสำหรับฉันไม่ใช่ pythonic ฉันเดา แต่:

ฉันใช้if __main__ ด้านบนของโมดูลที่ฉันต้องการแก้ปัญหาที่ทำงานจากเส้นทางที่แตกต่างจากปกติ

ดังนั้น:

# On top of the module, instead of on the bottom
import os
if __name__ == '__main__':
    os.chdir('/path/for/the/regularly/run/directory')
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.