Haruskah saya menggunakan `import os.path` atau` import os`?

139

Menurut dokumentasi resmi , os.pathadalah modul. Jadi, apa cara yang lebih disukai untuk mengimpornya?

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

Atau...

# Is importing os enough?
import os

Tolong JANGAN jawab "mengimpor oskarya untuk saya". Saya tahu, itu bekerja untuk saya juga sekarang (pada Python 2.6). Yang ingin saya ketahui adalah rekomendasi resmi tentang masalah ini. Jadi, jika Anda menjawab pertanyaan ini, silakan kirim referensi Anda .

Denilson Sa Maia
sumber

Jawaban:

157

os.pathbekerja dengan cara yang lucu. Sepertinya osharus paket dengan submodule path, tetapi dalam kenyataannya osadalah modul normal yang melakukan sihir dengan sys.modulesmenyuntikkan os.path. Inilah yang terjadi:

  • Ketika Python dimulai, ia memuat banyak modul ke dalamnya sys.modules. Mereka tidak terikat dengan nama apa pun di skrip Anda, tetapi Anda dapat mengakses modul yang sudah dibuat saat Anda mengimpornya dengan cara tertentu.

    • sys.modulesadalah dict di mana modul di-cache. Ketika Anda mengimpor modul, jika sudah diimpor di suatu tempat, itu membuat instance disimpan sys.modules.
  • osadalah salah satu modul yang dimuat ketika Python dimulai. Ini menetapkan pathatributnya ke modul jalur os-spesifik.

  • Itu menyuntikkan sys.modules['os.path'] = pathsehingga Anda dapat melakukan " import os.path" seolah-olah itu adalah submodule.

Saya cenderung menganggap os.pathsebagai modul yang ingin saya gunakan daripada sesuatu dalam osmodul , jadi meskipun itu bukan benar - benar sebuah submodul dari sebuah paket yang disebut os, saya mengimpornya seperti itu adalah satu dan saya selalu melakukannyaimport os.path . Ini konsisten dengan bagaimana os.pathdidokumentasikan.


Kebetulan, struktur semacam ini mengarah ke banyak kebingungan awal programmer Python tentang modul dan paket dan organisasi kode, saya pikir. Ini benar-benar karena dua alasan

  1. Jika Anda menganggap ossebagai paket dan tahu bahwa Anda dapat melakukan import osdan memiliki akses ke submodule os.path, Anda mungkin akan terkejut ketika Anda tidak dapat melakukan import twisteddan secara otomatis mengakses twisted.spreadtanpa mengimpornya.

  2. Ini membingungkan bahwa itu os.nameadalah hal yang normal, string, dan os.pathmerupakan modul. Saya selalu menyusun paket saya dengan __init__.pyfile kosong sehingga pada tingkat yang sama saya selalu memiliki satu jenis hal: modul / paket atau hal-hal lain. Beberapa proyek Python besar mengambil pendekatan ini, yang cenderung membuat kode lebih terstruktur.

Mike Graham
sumber
Jawaban yang sangat bagus dan sangat informatif! Selamat! Meskipun tidak langsung menjawab pertanyaan, ia memiliki banyak detail berguna. Tetapi bisakah Anda menjelaskan lebih lanjut tentang "Ini konsisten dengan bagaimana os.path didokumentasikan"? Seperti kata Chris Hulan, contoh os.walk () mengimpor hanya os, bukan os.path.
Denilson Sá Maia
3
@ Denilson, Ini memang termasuk jawaban langsung: Saya selalu melakukan import os.pathsendiri dan berpikir itu cara yang lebih baik. Dengan "Ini konsisten dengan bagaimana os.path didokumentasikan" Maksud saya diberikan halamannya sendiri dalam dokumentasi di docs.python.org/library/os.path.html .
Mike Graham
1
Wow, os.pymemang menyuntikkan ke sys.modules['os.path']. Jadi inilah mengapa from os.path import somethingsebenarnya bekerja. Saya ingin tahu tentang kapan ini diperkenalkan dan memeriksa sumbernya. Fakta menyenangkan: Ini dari tahun 1999, pertama kali dimasukkan dalam Python 1.5.2. Komit asli ada di sini .
Bluehorn
29

Sesuai PEP-20 oleh Tim Peters, "Eksplisit lebih baik daripada implisit" dan "jumlah keterbacaan". Jika semua yang Anda butuhkan dari osmodul berada di bawah os.path, import os.pathakan lebih eksplisit dan biarkan orang lain tahu apa yang Anda benar-benar pedulikan.

Demikian juga, PEP-20 juga mengatakan "Sederhana lebih baik daripada kompleks", jadi jika Anda juga membutuhkan barang-barang yang berada di bawah ospayung yang lebih umum , import osakan lebih disukai.

Nick T
sumber
2
Saya tidak melihat bagaimana import ossebenarnya menjadi "sederhana" dengan cara apa pun yang berarti. Sederhana! = Pendek.
Mike Graham
14
Saya lagi mencoba untuk menunjukkan bahwa import os dan sebuah import os.pathadalah bodoh jika Anda misalnya kebutuhan os.getcwd()danos.path.isfile()
Nick T
15

Jawaban pasti: import osdan gunakan os.path. jangan import os.pathlangsung.

Dari dokumentasi modul itu sendiri:

>>> 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).
...
lesmana
sumber
13
Perhatikan bahwa ini bukan dokumen untuk os.pathmodul yang tidak ada, tetapi untuk posixpath.
wRAR
18
Itu sama sekali bukan bagaimana saya berpikir bahwa docstring dimaksudkan untuk ditafsirkan, meskipun itu cukup menyesatkan. Ingatlah bahwa kalimat "Instead of importing this module directly, import os and refer to this module as os.path."tersebut berada di posixpath.py(atau macpath.py, ntpath.pydll.). Saya cukup yakin bahwa apa yang mereka maksud adalah bahwa seseorang tidak boleh import posixpath(yang bekerja), tetapi mengimpor modul via osuntuk portabilitas yang lebih baik. Saya tidak berpikir mereka bermaksud untuk memberikan rekomendasi apakah import osatau import os.pathlebih disukai.
flornquake
1
Saya setuju dengan sebagian besar komentar @flornquake tetapi tidak setuju dengan kalimat terakhir. Baik posixpath.py dan ntpath.py mengatakan "impor os dan lihat modul ini sebagai os.path". Mereka tidak mengatakan "impor os.path dan lihat modul ini sebagai os.path". macpath.py tidak memiliki apapun tentang masalah ini.
Pete Forman
3
Ini adalah contoh yang baik untuk menunjukkan bagaimana dokumen yang mengandung pointer ini dapat menyesatkan: D
Cyker
7

Yang cukup menarik, mengimpor os.path akan mengimpor semua os. coba yang berikut ini di prompt interaktif:

import os.path
dir(os)

Hasilnya akan sama seperti jika Anda baru saja mengimpor os. Ini karena os.path akan merujuk ke modul berbeda berdasarkan sistem operasi yang Anda miliki, jadi python akan mengimpor os untuk menentukan modul mana yang akan dimuat untuk path.

referensi

Dengan beberapa modul, mengatakan import footidak akan mengekspos foo.bar, jadi saya kira itu sangat tergantung pada desain modul tertentu.


Secara umum, hanya mengimpor modul eksplisit yang Anda butuhkan harus sedikit lebih cepat. Di mesin saya:

import os.path: 7.54285810068e-06 detik

import os: 9.21904878972e-06 detik

Waktu-waktu ini cukup dekat sehingga bisa diabaikan. Program Anda mungkin perlu menggunakan modul lain dari ossekarang atau nanti, jadi biasanya masuk akal hanya mengorbankan dua mikrodetik dan gunakan import osuntuk menghindari kesalahan ini di lain waktu. Saya biasanya berpihak dengan hanya mengimpor os secara keseluruhan, tetapi dapat melihat mengapa beberapa lebih suka secara import os.pathteknis lebih efisien dan menyampaikan kepada pembaca kode bahwa itu adalah satu-satunya bagian dari osmodul yang perlu digunakan. Ini pada dasarnya bermuara pada pertanyaan gaya dalam pikiran saya.

Matt Boehm
sumber
2
from os import pathakan membuat panggilan ke jalur lebih cepat jika kecepatan adalah masalah.
Justin Peel
Menjadi pythonic, eksplisit lebih baik daripada implisit kan? Pada kenyataannya saya pikir itu benar-benar panggilan penilaian oleh pengguna, apakah pengguna hanya akan menggunakan os.path atau beberapa modul di dalam os. Mungkin satu metode lebih sesuai dengan filosofi Anda?
Andrew Kou
23
Waktu ini adalah beberapa optimasi prematur prematur yang pernah saya lihat. Ini tidak pernah menjadi penghambat siapa pun dan waktu di sini tidak penting untuk bagaimana seseorang harus kode.
Mike Graham
5

Akal sehat bekerja di sini: osadalah modul, dan os.pathjuga modul. Jadi impor saja modul yang ingin Anda gunakan:

  • Jika Anda ingin menggunakan fungsionalitas dalam osmodul, maka impor os.

  • Jika Anda ingin menggunakan fungsionalitas dalam os.pathmodul, maka impor os.path.

  • Jika Anda ingin menggunakan fungsionalitas di kedua modul, maka impor kedua modul:

    import os
    import os.path

Sebagai referensi:

Cyker
sumber
4

Tidak dapat menemukan referensi pasti, tetapi saya melihat bahwa contoh kode untuk os.walk menggunakan os.path tetapi hanya mengimpor os

Chris Hulan
sumber