Tôi nên sử dụng `nhập os.path` hay` nhập os`?


139

Theo các tài liệu chính thức , os.pathlà một mô-đun. Vì vậy, cách nhập khẩu ưa thích là gì?

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

Hoặc là...

# Is importing os enough?
import os

Vui lòng KHÔNG trả lời "nhập oscông việc cho tôi". Tôi biết, nó cũng hoạt động với tôi ngay bây giờ (kể từ Python 2.6). Những gì tôi muốn biết là bất kỳ khuyến nghị chính thức về vấn đề này. Vì vậy, nếu bạn trả lời câu hỏi này, xin vui lòng gửi tài liệu tham khảo của bạn .

Câu trả lời:


157

os.pathhoạt động một cách hài hước. Có vẻ như oslà một gói với một mô hình con path, nhưng trong thực tế oslà một mô-đun bình thường có phép thuật sys.modulesđể tiêm os.path. Đây là những gì xảy ra:

  • Khi Python khởi động, nó tải một loạt các mô-đun vào sys.modules. Chúng không bị ràng buộc với bất kỳ tên nào trong tập lệnh của bạn, nhưng bạn có thể truy cập các mô-đun đã được tạo khi bạn nhập chúng theo một cách nào đó.

    • sys.moduleslà một lệnh trong đó các mô-đun được lưu trữ. Khi bạn nhập một mô-đun, nếu nó đã được nhập ở đâu đó, nó sẽ được lưu trữ trong trường hợp đó sys.modules.
  • oslà một trong các mô-đun được tải khi Python khởi động. Nó gán paththuộc tính của nó cho một mô-đun đường dẫn cụ thể os.

  • Nó tiêm sys.modules['os.path'] = pathđể bạn có thể làm " import os.path" như thể nó là một mô hình con.

Tôi có xu hướng nghĩ về os.pathnhư một module Tôi muốn sử dụng chứ không phải là một điều trong osmô-đun , vì vậy mặc dù nó không phải là thực sự một submodule của một gói gọi os, tôi nhập nó loại giống như nó là một và tôi luôn luôn làmimport os.path . Điều này phù hợp với cách os.pathghi chép.


Ngẫu nhiên, kiểu cấu trúc này dẫn đến rất nhiều sự nhầm lẫn ban đầu của các lập trình viên Python về các mô-đun và các gói và tổ chức mã, tôi nghĩ vậy. Điều này thực sự vì hai lý do.

  1. Nếu bạn nghĩ về osmột gói và biết rằng bạn có thể làm import osvà có quyền truy cập vào mô hình con os.path, bạn có thể ngạc nhiên sau đó khi bạn không thể làm import twistedvà tự động truy cập twisted.spreadmà không cần nhập nó.

  2. Điều khó hiểu os.namelà một điều bình thường, một chuỗi và os.pathlà một mô-đun. Tôi luôn cấu trúc các gói của mình với __init__.pycác tệp trống để ở cùng cấp tôi luôn có một loại: mô-đun / gói hoặc các thứ khác. Một số dự án Python lớn thực hiện phương pháp này, có xu hướng tạo mã có cấu trúc chặt chẽ hơn.


Tuyệt vời, câu trả lời rất nhiều thông tin! Xin chúc mừng! Mặc dù nó không trả lời trực tiếp câu hỏi, nhưng nó có rất nhiều chi tiết hữu ích. Nhưng bạn có thể giải thích rõ hơn về "Điều này phù hợp với cách os.path được ghi lại" không? Giống như Chris Hulan đã nói, ví dụ os.walk () chỉ nhập os thay vì os.path.
Denilson Sá Maia

3
@Denilson, Nó bao gồm một câu trả lời trực tiếp: Tôi luôn import os.pathtự làm và nghĩ rằng đó là một cách đẹp hơn. Bởi "Điều này phù hợp với cách os.path được ghi lại" Tôi có nghĩa là nó được cung cấp trang riêng trong tài liệu tại docs.python.org/l Library / os.path.html .
Mike Graham

1
Wow, os.pythực sự tiêm vào sys.modules['os.path']. Vì vậy, đây là lý do tại sao from os.path import somethingthực sự làm việc. Tôi đã tò mò về điều này khi được giới thiệu và kiểm tra nguồn. Sự thật thú vị: Đây là từ năm 1999, lần đầu tiên được bao gồm trong Python 1.5.2. Cam kết ban đầu là đây .
Bluehorn

29

Theo PEP-20 của Tim Peters, "Rõ ràng là tốt hơn ngầm định" và "Số lượng khả năng đọc". Nếu tất cả những gì bạn cần từ osmô-đun là dưới os.path, import os.pathsẽ rõ ràng hơn và cho người khác biết những gì bạn thực sự quan tâm.

Tương tự như vậy, PEP-20 cũng nói "Đơn giản là tốt hơn phức tạp", vì vậy nếu bạn cũng cần những thứ nằm dưới oschiếc ô chung hơn , import ossẽ được ưu tiên hơn.


2
Tôi không thấy cách import osthực sự "đơn giản" theo bất kỳ cách có ý nghĩa nào. Đơn giản! = Ngắn.
Mike Graham

14
Tôi đã nhiều cố gắng để chỉ ra rằng import os một import os.pathlà ngớ ngẩn nếu bạn ví dụ như nhu cầu os.getcwd()os.path.isfile()
Nick T

15

Câu trả lời dứt khoát: import osvà sử dụng os.path. không import os.pathtrực tiếp

Từ tài liệu của chính mô-đun:

>>> 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
Lưu ý rằng đó không phải là tài liệu cho một os.pathmô-đun không tồn tại mà dành cho posixpath.
wRAR

18
Đó không phải là tất cả những gì tôi nghĩ rằng docopes có nghĩa là được giải thích, mặc dù nó khá sai lệch. Hãy nhớ rằng câu "Instead of importing this module directly, import os and refer to this module as os.path."được đặt trong posixpath.py(hoặc macpath.py, ntpath.pyv.v.). Tôi khá chắc chắn rằng điều họ muốn nói là người ta không nên import posixpath(hoạt động), mà là nhập mô-đun qua osđể có tính di động tốt hơn. Tôi không nghĩ họ có ý định đưa ra một khuyến nghị về việc có import oshay không import os.pathđược ưu tiên.
flornquake

1
Tôi đồng ý với hầu hết bình luận của @flornquake nhưng không đồng ý với câu cuối cùng. Cả posixpath.py và ntpath.py đều nói "nhập os và gọi mô-đun này là os.path". Họ không nói "nhập os.path và gọi mô-đun này là os.path". macpath.py không có gì về vấn đề này.
Pete Forman

3
Đây là một ví dụ điển hình cho thấy tài liệu chứa con trỏ này có thể gây hiểu nhầm như thế nào : D
Cyker

7

Thật thú vị, nhập os.path sẽ nhập tất cả os. Hãy thử làm như sau trong lời nhắc tương tác:

import os.path
dir(os)

Kết quả sẽ giống như khi bạn vừa nhập os. Điều này là do os.path sẽ đề cập đến một mô-đun khác dựa trên hệ điều hành mà bạn có, vì vậy python sẽ nhập os để xác định mô-đun nào sẽ tải cho đường dẫn.

tài liệu tham khảo

Với một số mô-đun, việc nói import foosẽ không bị lộ foo.bar, vì vậy tôi đoán nó thực sự phụ thuộc vào thiết kế của mô-đun cụ thể.


Nói chung, chỉ cần nhập các mô-đun rõ ràng bạn cần phải nhanh hơn một chút. Trên máy của tôi:

import os.path: 7.54285810068e-06 giây

import os: 9.21904878972e-06 giây

Những thời điểm này là đủ gần để không đáng kể. Chương trình của bạn có thể cần phải sử dụng các mô-đun khác từ osbây giờ hoặc sau đó, vì vậy, sẽ rất hợp lý khi hy sinh hai micro giây và sử dụng import osđể tránh lỗi này sau đó. Tôi thường chỉ nhập toàn bộ os, nhưng có thể thấy lý do tại sao một số người thích import os.pathsử dụng hiệu quả hơn về mặt kỹ thuật và truyền đạt tới độc giả của mã đó là phần duy nhất của osmô-đun sẽ cần được sử dụng. Nó cơ bản sôi sục cho một câu hỏi phong cách trong tâm trí của tôi.


2
from os import pathsẽ làm cho các cuộc gọi đến đường dẫn thậm chí nhanh hơn nếu tốc độ là vấn đề.
Justin Peel

Là pythonic, rõ ràng là tốt hơn ngầm? Trong thực tế tôi nghĩ rằng đó thực sự là cuộc gọi phán xét của người dùng, cho dù người dùng sẽ chỉ sử dụng os.path hay nhiều mô-đun trong os. Có lẽ một phương pháp phù hợp hơn với triết lý của bạn so với phương pháp khác?
Andrew Kou

23
Thời điểm này là một số tối ưu hóa sớm nhất mà tôi từng thấy. Điều này chưa bao giờ nút cổ chai của bất kỳ ai và thời gian ở đây là không quan trọng đối với cách ai đó nên viết mã.
Mike Graham

5

Ý nghĩa thông thường hoạt động ở đây: oslà một mô-đun, và os.pathcũng là một mô-đun. Vì vậy, chỉ cần nhập mô-đun bạn muốn sử dụng:

  • Nếu bạn muốn sử dụng các chức năng trong osmô-đun, sau đó nhập os.

  • Nếu bạn muốn sử dụng các chức năng trong os.pathmô-đun, sau đó nhập os.path.

  • Nếu bạn muốn sử dụng các chức năng trong cả hai mô-đun, sau đó nhập cả hai mô-đun:

    import os
    import os.path

Để tham khảo:


4

Không thể tìm thấy bất kỳ tài liệu tham khảo chính xác nào, nhưng tôi thấy rằng mã ví dụ cho os.walk sử dụng os.path nhưng chỉ nhập os

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.