Ben var cevap Ben okuma dayalı anlaşılan düşünce Python mutlak ithalat, ilgili soru Python 2.5 changelog ve beraberindeki PEP . Ancak, Python 2.5'i yükledikten ve doğru bir şekilde kullanmanın bir örneğini oluşturmaya çalıştıktan sonra from __future__ import absolute_import
, şeylerin o kadar net olmadığını fark ettim.
Yukarıda bağlantılı değişiklik günlüğünden, bu ifade mutlak ithalat değişikliği hakkındaki anlayışımı doğru bir şekilde özetledi:
Diyelim ki böyle bir paket dizininiz var:
pkg/ pkg/__init__.py pkg/main.py pkg/string.py
Bu
pkg
,pkg.main
vepkg.string
alt modüllerini içeren adlı bir paketi tanımlar .Main.py modülündeki kodu düşünün. İfadeyi yürütürse ne olur
import string
? Python 2.4 ve öncesinde, göreceli bir içe aktarma gerçekleştirmek için paketin dizinine bakar, pkg / string.py dosyasını bulur, bu dosyanın içeriğinipkg.string
modül olarak içe aktarır"string"
vepkg.main
modül modülün ad alanındaki ada bağlanır .
Bu yüzden tam dizin yapısını oluşturdum:
$ ls -R
.:
pkg/
./pkg:
__init__.py main.py string.py
__init__.py
ve string.py
boş. main.py
aşağıdaki kodu içerir:
import string
print string.ascii_uppercase
Beklendiği gibi, bunu Python 2.5 ile çalıştırmak aşağıdakilerle başarısız olur AttributeError
:
$ python2.5 pkg/main.py
Traceback (most recent call last):
File "pkg/main.py", line 2, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
Bununla birlikte, 2.5 değişiklik günlüğünde, bunu buluyoruz (vurgu eklendi):
Python 2.5'te, yönerge
import
kullanarak davranışlarını mutlak içe aktarmalara geçirebilirsinizfrom __future__ import absolute_import
. Bu mutlak içe aktarma davranışı, gelecekteki bir sürümde varsayılan olabilir (muhtemelen Python 2.7). Mutlak içe aktarmalar varsayılan olduğunda,import string
her zaman standart kitaplığın sürümünü bulur.
Bu nedenle pkg/main2.py
, main.py
gelecekteki ek ithalat yönergesiyle özdeş ancak aynı şekilde oluşturdum . Şimdi şöyle görünüyor:
from __future__ import absolute_import
import string
print string.ascii_uppercase
Python 2.5 ile bu Koşu Ancak ... Bir başarısız olur AttributeError
:
$ python2.5 pkg/main2.py
Traceback (most recent call last):
File "pkg/main2.py", line 3, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
Bu , mutlak ithalatın etkin olduğu import string
her zaman std-lib sürümünü bulan ifadeyle oldukça çelişir . Dahası, mutlak ithalatın "yeni varsayılan" davranış olarak planlandığı uyarısına rağmen, aynı sorunu hem Python 2.7'yi kullanarak, hem de __future__
direktifle veya direktifsiz olarak vurdum :
$ python2.7 pkg/main.py
Traceback (most recent call last):
File "pkg/main.py", line 2, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
$ python2.7 pkg/main2.py
Traceback (most recent call last):
File "pkg/main2.py", line 3, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
Python 3.5 ile birlikte veya birlikte ( print
ifadenin her iki dosyada da değiştiği varsayılarak ):
$ python3.5 pkg/main.py
Traceback (most recent call last):
File "pkg/main.py", line 2, in <module>
print(string.ascii_uppercase)
AttributeError: module 'string' has no attribute 'ascii_uppercase'
$ python3.5 pkg/main2.py
Traceback (most recent call last):
File "pkg/main2.py", line 3, in <module>
print(string.ascii_uppercase)
AttributeError: module 'string' has no attribute 'ascii_uppercase'
Bunun diğer varyasyonlarını test ettim. Yerine string.py
adlı bir dizin -, boş bir modül oluşturduk string
sadece boş içeren __init__.py
- ve bunun yerine ithalatı verilmesine main.py
, ben cd
'için d pkg
ve repl doğrudan ithalat çalıştırın. Bu varyasyonların hiçbiri (ya da bunların bir kombinasyonu) yukarıdaki sonuçları değiştirmedi. Bunu __future__
direktif ve mutlak ithalatlar hakkında okuduğum şeyle uzlaştıramıyorum .
Bana öyle geliyor ki , aşağıdakiler tarafından kolayca açıklanabilir (bu Python 2 belgelerinden gelir, ancak bu ifade Python 3 için aynı belgelerde değişmeden kalır):
sys.path
(...)
Bu listenin ilk öğesi olan program başlangıcında başlatıldığı gibi
path[0]
, Python yorumlayıcısını çağırmak için kullanılan komut dosyasını içeren dizindir. Kod dizini kullanılamıyorsa (örneğin, yorumlayıcı etkileşimli olarak çağrılırsa veya kod standart girdiden okunursa), Python'u önce geçerli dizindeki modülleri aramaya yönlendirenpath[0]
boş dizedir .
O zaman neyi özlüyorum? İfade neden __future__
söylediği gibi görünmüyor ve bu çelişkinin belgelerin bu iki bölümü ile tarif edilen ve gerçek davranış arasındaki çözümü nedir?