Mengapa modul Python terkadang tidak mengimpor sub-modulnya?

91

Saya memperhatikan sesuatu yang aneh hari ini yang ingin saya jelaskan. Saya tidak 100% yakin bagaimana mengatakan ini sebagai pertanyaan, jadi google tidak mungkin. Modul logging tidak memiliki akses ke modul logging.handlers karena beberapa alasan aneh. Coba sendiri jika Anda tidak percaya saya:

>>> import logging
>>> logging.handlers
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'handlers'
>>> import logging.handlers
>>> logging.handlers
<module 'logging.handlers' from '/usr/lib/python2.6/logging/handlers.pyc'>

Adakah yang bisa menjelaskan mengapa ini terjadi?

chriscauley.dll
sumber

Jawaban:

122

Dalam Python, modul perlu diimpor sebelum dapat diakses. import loggingmengimpor hanya modul logging. Kebetulan itu loggingadalah paket dengan submodul, tetapi submodul tersebut masih tidak dimuat secara otomatis. Jadi, Anda perlu mengimpor secara eksplisit logging.handlerssebelum dapat mengaksesnya.

Jika Anda bertanya-tanya mengapa terkadang Anda tidak memerlukan impor tambahan tersebut: beberapa paket mengimpor beberapa atau semua submodulnya saat diimpor - cukup dengan melakukan impor tersebut di __init__.pyfile mereka . Dalam kasus lain, mungkin hal lain yang Anda impor, juga diimpor logging.handlers. Tidak masalah bagian kode mana yang diimpor; selama sesuatu dalam proses Anda diimpor logging.handlerssebelum Anda mengaksesnya, itu akan ada di sana. Dan terkadang modul yang terlihat seperti paket sebenarnya bukan modul, seperti osdan os.path. osbukan sebuah paket, ia hanya mengimpor modul lain yang benar (untuk platform Anda) dan memanggilnya path, agar Anda dapat mengaksesnya sebagai os.path.

Thomas Wouters
sumber
4

Saya juga baru mengenal python dan setelah banyak berlatih sekarang saya dapat membedakan antara, paket (folder), modul (.py), kelas, variabel ... dll ...

jika Anda ingin folder Anda menjadi paket python - Itu harus berisi __init__.pyfile bahkan file kosong akan dilakukan !!!

dan seperti kata Thomas, Anda dapat mengimpor modul tambahan di __init__.py jika Anda mau !!! tetapi modul / paket hanya dapat diakses setelah mengimpornya ...

jika Anda ingin mengimpor semuanya dari modul yang dapat Anda gunakan

from logging import *

selebihnya Anda dapat mengakses modul penangan seperti di bawah ini juga,

from logging import handlers
print dir(handlers)

shahjapan
sumber
5
Tolong jangan gunakan from module import *. Itu hampir selalu salah.
Thomas Wouters
Jika Anda ingin semua yang ada di dalam paket diimpor secara otomatis, lakukan impor itu di init .py, alih-alih menyetel semua di init .py dan melakukan 'from package import *' di suatu tempat.
Thomas Wouters
2
@ Pete: karena "mencemari" namespace standar yang mengarah ke ambiguitas dan konflik. Jika saya punya import zipperdan zipper.open()Anda akan tahu persis pembukaan mana yang saya panggil. Sebaliknya from zipper import *diikuti oleh open()apakah itu built-in open atau zipper.open atau sesuatu yang lain. import zipper as zlebih disukai jika Anda bosan mengetikzipper
msw
3
@ Pete: Ini juga masalah karena Anda mungkin menimpa beberapa namespace Anda tanpa disadari. Saya biasa menggunakan dari numpy import *karena beberapa fungsi numpy tidak berfungsi kecuali jika Anda mengimpor semua numpy (cacat desain yang buruk pada bagian IMO mereka) tetapi numpy memiliki sejumlah besar objek yang diimpor. Saya akhirnya menimpa banyak fungsi (saya yakin salinannya adalah satu ... Saya terlalu lelah untuk memeriksanya). Sekarang saya mengimpor numpy sebagai np jika saya akan menggunakan numpy begitu banyak sehingga saya tidak tahan untuk mengetiknya berulang kali.
chriscauley
2
@ dustynachos, fungsi numpy mana yang memiliki cacat itu?
Winston Ewert
2

Thomas Wouters menjawab pertanyaan ini dengan sangat baik, tetapi sayangnya, saya hanya menemukan pertanyaan ini setelah menemukan jawabannya di dokumentasi aslinya. Untuk itu saya pikir saya akan menambahkan ini dengan harapan itu muncul lebih dekat ke bagian atas mesin pencari di masa depan.

PERTANYAAN

Mengapa kesalahan: ' AttributeError: module' module_name 'tidak memiliki atribut' sub_module_name 'muncul meskipun editor saya (misalnya Visual Code) melengkapi nama sub-modul secara otomatis:

 import module_name
 module_name.sub_module_name(parameter)

MENJAWAB

Editor Anda mendasarkan pelengkapan otomatisnya dari struktur file proyek Anda dan bukan dari perilaku Python. Sub-modul tidak diimpor 'secara otomatis' saat Anda mengimpor modul. Referensi Dokumentasi Python untuk detail tentang cara mengimpor sub-modul 'secara otomatis' saat menggunakan

 import module_name

Kontribusi utama dengan jawaban ini adalah penambahan AttributeError saat mencoba mengimpor 'modul' atau 'paket'

Semoga ini bisa membantu seseorang!

Mengalir
sumber
1

Saya baru-baru ini menghadapi situasi aneh yang sama. Jadi, saya yakin Anda telah menghapus beberapa impor lib pihak ketiga. Lib yang dihapus itu berisi from logging import handlersatau from logging import *dan memberi Anda handlers. Dan di skrip lain Anda memiliki sesuatu yang seperti import loggingdan baru saja digunakan logging.handlersdan Anda berpikir itulah cara kerja saya.

Alexey
sumber