ฉันควรใช้ `import os.path` หรือ` import os` หรือไม่


139

อ้างอิงถึงเอกสารที่เป็นทางการ , os.pathเป็นโมดูล ดังนั้นวิธีการนำเข้าที่ต้องการคืออะไร

# Should I always import it explicitly?
import os.path

หรือ...

# Is importing os enough?
import os

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

คำตอบ:


157

os.pathทำงานในวิธีที่ตลก ดูเหมือนว่าosควรจะเป็นแพคเกจกับ submodule pathแต่ในความเป็นจริงosเป็นโมดูลที่ไม่ปกติมายากลที่มีการฉีดsys.modules os.pathนี่คือสิ่งที่เกิดขึ้น:

  • เมื่อ Python เริ่มทำงานมันจะโหลดโมดูลจำนวนsys.modulesมากเข้ามา พวกเขาจะไม่ผูกพันกับชื่อใด ๆ ในสคริปต์ของคุณ แต่คุณสามารถเข้าถึงโมดูลที่สร้างขึ้นแล้วเมื่อคุณนำเข้าพวกเขาในบางวิธี

    • sys.modulesเป็น dict ที่โมดูลถูกแคช sys.modulesเมื่อคุณนำเข้าโมดูลถ้ามันมีอยู่แล้วได้ถูกนำเข้าที่ไหนสักแห่งจะได้รับตัวอย่างที่เก็บไว้ใน
  • osเป็นหนึ่งในโมดูลที่โหลดเมื่อ Python เริ่มทำงาน มันกำหนดpathคุณสมบัติของมันให้กับโมดูลเส้นทางเฉพาะ OS

  • มันฉีดsys.modules['os.path'] = pathเพื่อให้คุณสามารถทำ "import os.pathเหมือนว่าเป็น submodule

ฉันมักจะคิดว่าos.pathเป็นโมดูลฉันต้องการใช้มากกว่าสิ่งที่ในส่วนosโมดูลดังนั้นแม้ว่ามันไม่ได้จริงๆ submodule ของแพคเกจที่เรียกว่าosผมนำเข้าจัดเรียงของชอบก็เป็นหนึ่งและฉันมักจะทำ import os.pathซึ่งสอดคล้องกับวิธีการos.pathจัดทำเอกสาร


โครงสร้างแบบนี้นำไปสู่ความสับสนในช่วงแรกของโปรแกรมเมอร์ Python เกี่ยวกับโมดูลและแพ็คเกจและการจัดระเบียบโค้ด นี่คือเหตุผลสองประการ

  1. หากคุณคิดว่าosเป็นแพคเกจและรู้ว่าคุณสามารถทำได้import osและมีสิทธิ์เข้าถึง submodule os.pathคุณอาจแปลกใจในภายหลังเมื่อคุณไม่สามารถทำได้import twistedและเข้าถึงโดยอัตโนมัติtwisted.spreadโดยไม่ต้องนำเข้า

  2. มันสับสนว่าos.nameเป็นเรื่องปกติสตริงและos.pathเป็นโมดูล ฉันมักจะจัดโครงสร้างแพ็กเกจของฉันด้วย__init__.pyไฟล์ว่างเปล่าเพื่อให้อยู่ในระดับเดียวกันฉันมักจะมีสิ่งหนึ่งประเภท: โมดูล / แพ็กเกจหรือสิ่งอื่น ๆ โครงการ Python ขนาดใหญ่หลายโครงการใช้แนวทางนี้ซึ่งมีแนวโน้มที่จะสร้างโค้ดที่มีโครงสร้างมากขึ้น


ยอดเยี่ยมคำตอบที่ให้ข้อมูลมาก! ขอแสดงความยินดี! แม้ว่ามันจะไม่ตอบคำถามโดยตรง แต่ก็มีรายละเอียดที่เป็นประโยชน์มากมาย แต่คุณช่วยอธิบายรายละเอียดเกี่ยวกับ "สิ่งนี้สอดคล้องกับวิธีการจัดทำเอกสาร os.path" ได้อย่างไร? เช่นเดียวกับ Chris Hulan กล่าวว่าตัวอย่าง os.walk () นำเข้าเพียงแค่ระบบปฏิบัติการแทนที่จะเป็น os.path
Denilson Sá Maia

3
@Denilson มันมีคำตอบโดยตรง: ฉันมักจะทำimport os.pathเองและคิดว่ามันเป็นวิธีที่ดีกว่า โดย "ซึ่งสอดคล้องกับวิธี os.path เป็นเอกสาร" ผมหมายความว่ามันจะได้รับหน้าของตัวเองในเอกสารที่docs.python.org/library/os.path.html
Mike Graham

1
ว้าวos.pyจะฉีดเข้าไปจริงsys.modules['os.path']ๆ นี่คือสาเหตุที่from os.path import somethingใช้งานได้จริง ฉันอยากรู้ว่าเมื่อไหร่ที่มีการเปิดตัวและตรวจสอบแหล่งที่มา สนุกจริง: นี่คือจากปี 1999 รวมอยู่ใน Python 1.5.2 เป็นครั้งแรก ต้นฉบับกระทำคือที่นี่
Bluehorn

29

ตามPEP-20โดย Tim Peters "Explicit ดีกว่า implicit" และ "readability counts" หากสิ่งที่คุณต้องการจากosโมดูลที่อยู่ภายใต้os.path,import os.pathจะมีความชัดเจนมากขึ้นและปล่อยให้คนอื่นรู้ว่าสิ่งที่คุณจริงๆดูแลเกี่ยวกับ

ในทำนองเดียวกัน PEP-20 ก็บอกว่า "Simple is better than complex" ดังนั้นหากคุณต้องการสิ่งที่อยู่ภายใต้osร่มimport osที่กว้างกว่าเช่นกัน


2
ฉันไม่เห็นว่าimport osการ "เรียบง่าย" นั้นมีความหมายอย่างไร ง่าย! = สั้น
Mike Graham

14
ผมก็พยายามที่จะชี้ให้เห็นว่าimport os และimport os.pathคือบ้าถ้าคุณเช่นความจำเป็นos.getcwd()และos.path.isfile()
นิคที

15

คำตอบที่ชัดเจน: และการใช้งานimport os os.pathทำไม่ได้import os.pathโดยตรง

จากเอกสารของโมดูลเอง:

>>> import os
>>> help(os.path)
...
Instead of importing this module directly, import os and refer to
this module as os.path.  The "os.path" name is an alias for this
module on Posix systems; on other systems (e.g. Mac, Windows),
os.path provides the same operations in a manner specific to that
platform, and is an alias to another module (e.g. macpath, ntpath).
...

13
โปรดทราบว่ามันไม่ได้เป็นเอกสารสำหรับos.pathโมดูลซึ่งไม่ได้อยู่ posixpathแต่สำหรับ
wRAR

18
นั่นไม่ใช่วิธีที่ฉันคิดว่า docstring นั้นควรถูกตีความแม้ว่ามันจะทำให้เข้าใจผิด โปรดทราบว่าประโยค"Instead of importing this module directly, import os and refer to this module as os.path."ตั้งอยู่posixpath.py(หรือmacpath.py, ntpath.pyฯลฯ ) ฉันค่อนข้างแน่ใจว่าสิ่งที่พวกเขาหมายถึงคือไม่ควรใช้import posixpath(ใช้งานได้) แต่นำเข้าโมดูลผ่านosเพื่อความสะดวกในการพกพา ฉันไม่คิดว่าพวกเขาตั้งใจจะให้คำแนะนำว่าเหมาะสมimport osหรือimport os.pathไม่
flornquake

1
ฉันเห็นด้วยกับความคิดเห็นส่วนใหญ่ของ @flornquake แต่ไม่เห็นด้วยกับประโยคสุดท้าย ทั้ง posixpath.py และ ntpath.py พูดว่า "import os และอ้างถึงโมดูลนี้เป็น os.path" พวกเขาไม่พูดว่า "import os.path และอ้างถึงโมดูลนี้เป็น os.path" macpath.py ไม่มีอะไรในเรื่องนี้
Pete Forman

3
นี่เป็นตัวอย่างที่ดีในการแสดงให้เห็นว่าเอกสารประกอบด้วยเอกสารนี้อย่างไรตัวชี้สามารถทำให้เข้าใจผิดได้อย่างไร: D
Cyker

7

ที่น่าสนใจคือการนำเข้า os.path จะนำเข้าระบบปฏิบัติการทั้งหมด ลองทำสิ่งต่อไปนี้ในหน้าจอโต้ตอบแบบโต้ตอบ:

import os.path
dir(os)

ผลลัพธ์จะเหมือนกับว่าคุณเพิ่งนำเข้าระบบปฏิบัติการ นี่เป็นเพราะ os.path จะอ้างถึงโมดูลที่แตกต่างกันตามระบบปฏิบัติการที่คุณมีดังนั้น python จะนำเข้าระบบปฏิบัติการเพื่อพิจารณาว่าจะโหลดโมดูลใดสำหรับพา ธ

การอ้างอิง

ในบางโมดูลการพูดimport fooจะไม่เปิดเผยfoo.barดังนั้นฉันเดาว่ามันขึ้นอยู่กับการออกแบบของโมดูลเฉพาะ


โดยทั่วไปเพียงแค่นำเข้าโมดูลที่ชัดเจนที่คุณต้องการควรรวดเร็วขึ้นเล็กน้อย บนเครื่องของฉัน:

import os.path: 7.54285810068e-06วินาที

import os: 9.21904878972e-06วินาที

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


2
from os import pathจะทำให้การเรียกไปยังเส้นทางเร็วยิ่งขึ้นถ้าความเร็วเป็นปัญหา
Justin Peel

การเป็นไพ ธ อนชัดเจนชัดเจนกว่าโดยปริยายใช่มั้ย ในความเป็นจริงฉันคิดว่าจริง ๆ แล้วมันเป็นการใช้วิจารณญาณของผู้ใช้ไม่ว่าผู้ใช้จะใช้ os.path หรือหลายโมดูลภายในระบบปฏิบัติการเท่านั้น บางทีวิธีการหนึ่งอาจสอดคล้องกับปรัชญาของคุณมากกว่าวิธีอื่น ๆ หรือไม่
Andrew Kou

23
การกำหนดเวลานี่คือการเพิ่มประสิทธิภาพก่อนเวลาอันควรบางอย่างก่อนกำหนดที่ฉันเคยเห็น สิ่งนี้ไม่เคยเป็นปัญหาคอขวดของใครเลยและเวลาที่นี่ไม่มีสาระสำคัญต่อการที่คนควรเขียนโค้ด
Mike Graham

5

สามัญสำนึกใช้งานได้ที่นี่: osเป็นโมดูลและos.pathเป็นโมดูลด้วย ดังนั้นเพียงนำเข้าโมดูลที่คุณต้องการใช้:

  • หากคุณต้องการใช้ฟังก์ชันในโมดูลนำเข้าแล้วosos

  • หากคุณต้องการใช้ฟังก์ชันในโมดูลนำเข้าแล้วos.pathos.path

  • หากคุณต้องการใช้ฟังก์ชันการทำงานในทั้งสองโมดูลให้นำเข้าทั้งสองโมดูล:

    import os
    import os.path

สำหรับการอ้างอิง:


4

ไม่พบการอ้างอิงที่ชัดเจนใด ๆ แต่ฉันเห็นว่าตัวอย่างโค้ดสำหรับos.walkใช้ os.path แต่นำเข้าเฉพาะระบบปฏิบัติการ

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