Python'daki göreceli içe aktarmaların nesi yanlış?


89

Kısa süre önce popüler bir Python tarzı denetleyicisi olan pylint'in sürümlerini yükselttim .

Tüm paket yolunu belirtmeden, aynı paket içinde modülleri içe aktardığım yerleri işaret ederek kodum boyunca balistik hale geldi.

Yeni hata mesajı W0403.

W0403:% r göreli ithalat,% r olmalıdır

Paket dizinine göre bir içe aktarma algılandığında kullanılır.


Örnek

Örneğin, paketlerim böyle yapılandırılmışsa:

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

ve sünger paketinde yazarım:

import icing

onun yerine

import cake.icing

Bu hatayı alacağım.


Pylint mesajlarının hepsinin eşit derecede önemli olmadığını anladığım halde bunları reddetmekten korkmuyorum, böyle bir uygulamanın neden kötü bir fikir olarak değerlendirildiğini anlamıyorum.

Birisinin tuzakları açıklayabileceğini umuyordum, bu yüzden kodlama tarzımı (şu an yapmayı planladığım gibi) bu görünüşte sahte uyarıyı kapatmak yerine geliştirebilirdim.

Yanıtlar:


97

Bunun sorunu, import icingbunun mutlak bir ithalat mı yoksa göreceli bir ithalat mı olduğunu bilmemenizdir. icingpython yolunda bir modül veya mevcut modülde bir paket olabilir. Yerel bir paket bir python standart kütüphane paketiyle aynı ada sahip olduğunda bu oldukça can sıkıcıdır.

from __future__ import absolute_importÖrtük göreli ithalatı tamamen kapatarak bunu yapabilirsiniz . Belirsizlik konusundaki bu gerekçeyle birlikte, PEP 328'de açıklanmaktadır . Python 3000'in göreceli ithalatı tamamen kapattığını düşünüyorum.

Hala göreceli ithalat yapabilirsiniz, ancak bunları açıkça yapmanız gerekir, şöyle:

from . import icing

2
Özellikle uzlaşma çözümü için +1, muhtemelen gitmem gereken yol bu.
Tuhaf,

2
Ayrıca import .icingbunun yerine yapabileceğinizi unutmayınfrom . import icing
Jack

11
@ Jack aslında yapabileceğini sanmıyorum. Gönderen PEP328 bu bölümünde : Göreli ithalat daima kullanmalısınız from <> import; import <>her zaman mutlaktır. Tabii ki, mutlak ithalat from <> import, öndeki noktaları atlayarak kullanabilir . Nedeni import .fooyasak çünkü import XXX.YYY.ZZZo zamandan sonra XXX.YYY.ZZZbir ifadede kullanılabilir. Ancak .moduleYbir ifadede kullanılamaz.
A.Wan

48

Bunun birkaç iyi nedeni var:

  1. Bir modülü hareket ettirdiğinizde göreceli ithalat kolayca kırılır.

    Paketinde bir foo.bar, bir foo.bazve bir bazmodül olduğunu hayal et . foo.bariçe aktarır foo.baz, ancak göreceli içe aktarma kullanır

    Taşımak olsaydı Şimdi, foo.bariçin bar, sizin modül aniden farklı bir ithal edilmektedir baz!

  2. Nispi ithalat belirsizdir. barYukarıdaki örnekte modülün etrafında hareket etmeden bile , projenize gelen yeni bir geliştirici , kök düzey paketi yerine bunun bazgerçek olduğunu anlamadığı için affedilebilir .foo.bazbaz

    Mutlak ithalat, hangi modülün kullanıldığını açıkça ortaya koymaktadır. Ve import thisvaaz, açık örtük daha iyidir.

  3. Python 3, örtük göreli ithalatı tamamen devre dışı bıraktı; ithalatlar şimdi her zaman mutlak olarak yorumlanır, yani yukarıdaki örnekte import bazher zaman en üst seviye modülü alırsınız. Bunun yerine açık içe aktarma sözdizimini kullanmanız gerekir ( from . import baz).

    Örneği Python 2'den 3'e taşımak, beklenmedik sorunlara neden olur; mutlak içe aktarmaların kullanılması şimdi kodunuzu geleceğe hazırlar.


10
# 2 ve # 3 için +1. Ancak, # 1 tüm dizin taşındığında ne olacağı ile dengelenmelidir (örneğin, bir seviyeyi aşağı itti).
Tuhaf,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.