Python modülünün mutlak ve açık göreli içe aktarımı


90

Bir Python uygulamasında paketleri içe aktarmanın tercih edilen yolunu merak ediyorum. Bunun gibi bir paket yapım var:

project.app1.models
project.app1.views
project.app2.models

project.app1.viewsithalat project.app1.modelsve project.app2.models. Bunu yapmanın akla gelen iki yolu var.

Mutlak ithalatla:

import A.A
import A.B.B

veya PEP 328 ile Python 2.5'te tanıtıldığı gibi açık göreli içe aktarımlarla :

# explicit relative
from .. import A
from . import B

Bunu yapmanın en pitonik yolu nedir?


"açık göreli" örnekler sözdizimi hatalarıdır. Bağıl ithalatı biçiminde olmalıdır from _ import ..., bu nedenle örnekler olacaktır from .. import Avefrom . import B
MestreLion

@MestreLion İyi yakaladın, kesinlikle haklısın! Ben benim sorum güncellenen import ..Aiçin from .. import A. Dikkat çekici bir şekilde birinin farkına
varması

Yanıtlar:


56

Mutlak ithalatlar. PEP 8'den:

Paket içi ithalatlar için göreli ithalatlar kesinlikle tavsiye edilmiyor. Tüm içe aktarmalar için her zaman mutlak paket yolunu kullanın. PEP 328 [7] Python 2.5'te tamamen uygulandığı şu anda bile, açıkça göreli içe aktarma tarzı etkin bir şekilde önerilmez; mutlak içe aktarmalar daha taşınabilir ve genellikle daha okunabilirdir.

Açık göreli içe aktarmalar güzel bir dil özelliğidir (sanırım), ancak mutlak içe aktarmalar kadar açık değildir. Daha okunaklı form:

import A.A
import A.B.B

özellikle birkaç farklı ad alanını içe aktarırsanız. Paketlerin içinden ithalatı içeren bazı iyi yazılmış projelere / öğreticilere bakarsanız, genellikle bu tarzı izlerler.

Daha açık hale getirmek için aldığınız birkaç ekstra tuş vuruşu, başkalarına (ve belki de size) gelecekte ad alanınızı anlamaya çalışırken (özellikle paketin bir kısmının bulunduğu 3.x'e geçiş yaparsanız) bolca zaman kazandıracaktır. isimler değişti).


@Rafe, "iyi yazılmış bazı projelere bakın ..." herhangi bir öneriniz var mı?
denis

@Denis: Rietveld, Guido van Rossum'un kendi projesi, bu yüzden oranın bakmak için iyi bir yer olacağını hayal ediyorum ( code.google.com/p/rietveld ) Python standart kitaplığı o kadar harika değil, bu kodun çoğu kurallara uymuyor.
Rafe Kettler

68
@Rafe: Guido'ya göre PEP-8'in bu kısmı modası geçmiş. mail.python.org/pipermail/python-dev/2010-Ekim/104476.html
Brandon Rhodes

13
Bu ifade artık PEP-8'de değil. Şimdi mutlak ithalatın tavsiye edildiğini ancak göreli ithalatın kabul edilebilir bir alternatif olduğunu belirtiyor.
dano

6
Mutlak ithalatla ilgili yaşadığım sorun, başka bir paket içindeki bir paketi kullanırken. Benim durumumda, git alt modülü olarak mevcut. Bu durumda, üst seviye paketi içe aktarabilsem de, bunun altındaki paketler, kendi modüllerini mutlak içe aktarmalarla bulamadıkları için içe aktarılamıyor. Oysa bu alt seviyede göreli ithalatı kullanırsam, hepsi işe yarıyor.
Davida

125

Python göreli içe aktarmalar artık kesinlikle tavsiye edilmemektedir, ancak bu durumda mutlak_import'un kullanılması şiddetle önerilir.

Lütfen Guido'nun kendisinden alıntı yapan bu tartışmaya bakın :

"Bu çoğunlukla tarihsel değil mi? Yeni göreli ithalat sözdizimi uygulanana kadar göreli ithalata ilişkin çeşitli sorunlar vardı. Kısa vadeli çözüm, bunları kullanmamayı önermekti. Uzun vadeli çözüm, kesin bir sözdizimi uygulamaktı. Şimdi anti-tavsiyeyi geri çekmenin zamanı geldi. Tabii ki, denize düşmeden - hala onlara kazanılmış bir zevk buluyorum; ama onların yeri var. "

OP , şunu söyleyen PEP 328'i doğru şekilde bağlar :

En önemlisi, alt paketleri düzenlemek zorunda kalmadan büyük paketlerin yapısını yeniden düzenleyebilmek olan birkaç kullanım durumu sunuldu. Ek olarak, bir paketin içindeki bir modül, göreli içe aktarmalar olmadan kendisini kolayca içe aktaramaz.

Ayrıca neredeyse yinelenen soruya bakın neden Python göreli ithalat kullanmak veya

Elbette hala bir zevk meselesi olarak duruyor. Göreceli içe aktarmalarla kodu taşımak daha kolay olsa da, bu beklenmedik bir şekilde işleri bozabilir; ve ithalatı yeniden adlandırmak o kadar da zor değil.

PEP 328'den yeni davranışı zorlamak için şunu kullanın:

from __future__ import absolute_import

Bu durumda, örtük göreceli içe aktarma artık mümkün import localfileolmayacaktır (örn. Artık çalışmayacaktır, yalnızca from . import localfile). Temiz ve ileride kanıtlanmış davranış için, absolute_import kullanılması tavsiye edilir.

Önemli bir uyarı, PEP 338 ve PEP 366 nedeniyle , göreceli içe aktarımların python dosyasının bir modül olarak içe aktarılmasını gerektirmesidir - göreceli içe aktarımı olan bir file.py'yi yürütemezsiniz veya bir ValueError: Attempted relative import in non-package.

En iyi yaklaşım değerlendirilirken bu sınırlama dikkate alınmalıdır. Guido, her durumda bir modülden komut dosyası çalıştırmaya karşıdır:

Bu konuda ve __main__ makinenin diğer önerilen oynamalarında -1'im. Tek kullanım durumu, her zaman bir anti-model olarak gördüğüm bir modülün dizininde yaşayan betikleri çalıştırmak gibi görünüyor. Fikrimi değiştirmemi sağlamak için, beni öyle olmadığına ikna etmelisin.

Konuyla ilgili kapsamlı tartışmalar SO'da bulunabilir; yeniden. Python 3 bu oldukça kapsamlıdır:


9
Guido bunu 2010'da yazdı ve hala PEP'te mi? Bu kadar modası geçmişlerse KEP'lere nasıl güvenebiliriz?
Jabba

2
PEP, bazı şeyleri değiştirebileceğiniz anlamında ABD'deki değişiklikler gibidir. Çok sayıda reddedilen PEPS de var. KEP'ler tekliflerdir. Kabul edilebilir, reddedilebilir veya geçerliliğini yitirebilir, bu da genellikle yeni PEP anlamına gelir. PEP 8 bir stil kılavuzudur, bu nedenle yerinde değiştirilebilir.
CppLearner

2
"Bir paketin içindeki modül kendini kolayca içe aktaramaz ..." kısmı konusunda kafam karıştı. Daha önce modüllerin ithal edildiğini hiç duymamıştım.
matiascelasco

2
Olası bir örnek @matiascelasco: foo / bar.py ve foo / baz.py'in yanı sıra başka bir yerde baz.py varsa. Foo.baz'ı bar'dan içe aktarmak istiyorsanız, neyi içe aktardığınızdan emin olmak isteyebilirsiniz, örn. import .baz- bu, yine de KEP'de açıklanan birçok benzer durumdan sadece bir tanesidir.
Stefano

Cevabınız, onlara izin vermedeki değişikliği açıkça ayırt etmiyor. Örtük göreceli içe aktarmalar asla kullanılmamalıdır, ancak açık göreli içe aktarmalar kullanılabilir. Python3'ten örtük göreli kaldırıldı.
ninMonkey

33

Göreli içe aktarmalar, daha sonra düzinelerce dahili içe aktarmayı değiştirmeden paketinizi yeniden adlandırmanız için sizi özgür bırakmaz, aynı zamanda onlarla döngüsel içe aktarma veya ad alanı paketleri gibi şeyleri içeren belirli sorunları çözmede başarılı oldum, çünkü bunlar Python'u " üst düzey ad alanından sonraki modülü aramaya baştan başlamak için top ".


4
Python stil kılavuzuna göre önerilmeyen stil budur. Okunabilirliği ciddi şekilde bulutlandırırlar ve sizin bahsettiğiniz algılanan "rahatlığa" değmezler. Bir sorunu çözmek için göreceli içe aktarım kullanmanız gerekiyorsa, yanlış yapıyorsunuz demektir.
Rafe Kettler

14
Onun (Brandon Rhodes) diğer cevap hakkındaki yorumuna, cevabın artık cesaretinin kırılmadığını gösteren bir bağlantıya dikkat edin.
Jon Coombs

1
@RafeKettler, kendisi başka bir pakette bulunan bir pakette mutlak ithalatı nasıl kullanacağınızı açıklar mısınız? Yeni üst düzey hakkında bilgi sahibi olmadıkları için, mutlak içe aktarmalar iç pakette başarısız olacaktır. Göreli ithalat işlemeye devam ediyor. Muhtemelen paketin ilk etapta bir başkasının içine yerleştirilmemesi gerektiği iddia edilebilir, ancak bazı kodların yeniden kullanılabilir olması amaçlanmıştır ve bu çok sık olur. Yeniden kullanılan kodların çoğu halka açık değildir ve bu nedenle ayrı bir paket olarak
sunulmaz, bu nedenle

3
@meowsqueak Kabul ediyorum, bazı paketler kolayca kurulamaz (pip üzerinde değiller, kullanmak istemiyorsunuz python setup.py installveya python setup.py developherhangi bir nedenle), bu durumlarda kaynak kodunu çatallayıp git alt modülü olarak ekliyorum. Bu paketler kendi paket adlarında mutlak içe aktarma kullandığında, içe aktarmaları başarısız olur. Tek çözüm, açık göreli ithalatlar kullanmaktır. Bence teşvik edilmesi gereken bu.
CMCDragonkai
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.