Apa yang salah dengan impor relatif di Python?

89

Baru-baru ini saya meningkatkan versi pylint , pemeriksa gaya Python yang populer.

Itu sudah balistik di seluruh kode saya, menunjukkan tempat di mana saya mengimpor modul dalam paket yang sama, tanpa menentukan jalur paket lengkap.

Pesan kesalahan baru adalah W0403.

W0403: Impor relatif% r, harus% r

Digunakan ketika impor relatif ke direktori paket terdeteksi.


Contoh

Misalnya, jika paket saya disusun seperti ini:

/cake
  /__init__.py
  /icing.py
  /sponge.py
/drink

dan dalam paket spons saya tulis:

import icing

dari pada

import cake.icing

Saya akan mendapatkan kesalahan ini.


Meskipun saya mengerti bahwa tidak semua pesan Pylint memiliki kepentingan yang sama, dan saya tidak takut untuk mengabaikannya, saya tidak mengerti mengapa praktik semacam itu dianggap sebagai ide yang buruk.

Saya berharap seseorang bisa menjelaskan perangkap, jadi saya bisa meningkatkan gaya pengkodean saya daripada (seperti yang saya rencanakan saat ini) mematikan peringatan yang tampaknya palsu ini.

Berpikir aneh
sumber

Jawaban:

98

Masalahnya import icingadalah Anda tidak tahu apakah itu impor absolut atau impor relatif. icingbisa modul di jalur python, atau paket di modul saat ini. Ini sangat menjengkelkan ketika paket lokal memiliki nama yang sama dengan paket pustaka standar python.

Anda dapat melakukan from __future__ import absolute_importyang mematikan impor relatif implisit sama sekali. Dijelaskan, termasuk dengan justifikasi tentang ambiguitas ini, dalam PEP 328 . Saya percaya Python 3000 memiliki impor relatif implisit dimatikan sepenuhnya.

Anda masih dapat melakukan impor relatif, tetapi Anda harus melakukannya secara eksplisit, seperti ini:

from . import icing
Winston Ewert
sumber
2
+1 terutama untuk solusi kompromi, yang mungkin harus saya jalani.
Oddthinking
2
Perhatikan, Anda juga bisa melakukannya import .icingdaripadafrom . import icing
Jack
11
@ Jack sebenarnya saya tidak berpikir Anda bisa. Dari bagian PEP328 ini : Impor relatif harus selalu digunakan from <> import; import <>selalu absolut. Tentu saja, impor absolut dapat digunakan from <> importdengan menghilangkan titik-titik terkemuka. Alasannya import .foodilarang adalah karena setelah import XXX.YYY.ZZZitu XXX.YYY.ZZZdapat digunakan dalam ekspresi. Tetapi .moduleYtidak bisa digunakan dalam ekspresi.
A.Wan
47

Ada beberapa alasan bagus:

  1. Impor relatif mudah rusak, saat Anda memindahkan modul.

    Bayangkan Anda memiliki modul foo.bar, a , foo.bazdan bazmodul dalam paket Anda. foo.barimpor foo.baz, tetapi menggunakan impor relatif.

    Sekarang, jika Anda pindah foo.barke bar, modul Anda tiba-tiba mengimpor yang berbeda baz!

  2. Impor relatif bersifat ambigu. Bahkan tanpa berpindah-pindah barmodul pada contoh di atas, pengembang baru yang datang ke proyek Anda dapat dimaafkan karena tidak menyadari bahwa bazitu sebenarnya foo.bazbukan bazpaket tingkat root .

    Impor absolut menjelaskan modul apa yang sedang digunakan. Dan sebagai import thiskhotbah, eksplisit lebih baik daripada implisit.

  3. Python 3 telah menonaktifkan impor relatif implisit sama sekali; impor sekarang selalu diartikan sebagai absolut, artinya dalam contoh di atas import bazakan selalu mengimpor modul tingkat atas. Anda harus menggunakan sintaks impor eksplisit sebagai gantinya ( from . import baz).

    Porting contoh dari Python 2 ke 3 akan menyebabkan masalah yang tidak terduga, menggunakan impor absolut sekarang akan membuat kode Anda menjadi bukti masa depan.

Martijn Pieters
sumber
11
+1 untuk # 2 dan # 3. Tetapi # 1 harus diimbangi dengan apa yang terjadi ketika seluruh direktori dipindahkan (misalnya didorong ke bawah tingkat).
Oddthinking