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.pyBu
pkg,pkg.mainvepkg.stringalt 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.stringmodül olarak içe aktarır"string"vepkg.mainmodü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__.pyve string.pyboş. main.pyaş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
importkullanarak 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 stringher zaman standart kitaplığın sürümünü bulur.
Bu nedenle pkg/main2.py, main.pygelecekteki 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 stringher 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 ( printifadenin 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.pyadlı bir dizin -, boş bir modül oluşturduk stringsadece boş içeren __init__.py- ve bunun yerine ithalatı verilmesine main.py, ben cd'için d pkgve 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?