Modül __file__ özniteliği mutlak mı yoksa göreceli mi?


107

Anlamakta güçlük çekiyorum __file__. Anladığım kadarıyla, __file__modülün yüklendiği mutlak yolu döndürür.

Bunu üretirken sorun yaşıyorum: İadelerden çalışan abc.pytek bir ifadem var . iadelerden kaçmak . Herhangi bir neden var mı?print __file__/d/projects/ python abc.pyabc.py/d/projects/abc.py



Yanıtlar:


98

Gönderen belgeler :

__file__bir dosyadan yüklenmişse, modülün yüklendiği dosyanın yol adıdır. __file__Nitelik statik tercüman içine bağlandıkları C modülleri için mevcut değildir; paylaşılan bir kitaplıktan dinamik olarak yüklenen uzantı modülleri için, paylaşılan kitaplık dosyasının yol adıdır.

Gönderen posta listesi iplik soruya bir yorum @kindall ile bağlantılı:

Bu belirli örneği yeniden oluşturmaya çalışmadım, ancak bunun nedeni her içe aktarmada getpwd () 'yi çağırmak zorunda kalmamamız ve geçerli dizini önbelleğe almak için bir tür işlem içi değişkene sahip olmak istemememizdir. (getpwd () göreceli olarak yavaştır ve bazen doğrudan başarısız olabilir ve önbelleğe almaya çalışırken yanlış olma riski vardır.)

Bunun yerine yaptığımız şey, site.py'deki sys.path öğelerinin üzerinden geçen ve onları mutlak yollara dönüştüren koddur. Ancak bu kod, sys.path'in önüne '' eklenmeden önce çalışır, böylece sys.path'in başlangıç ​​değeri '' olur.

Bunun geri kalanı sys.pathiçin dahil etmemeyi düşünün ''.

Dolayısıyla, sys.pathmodülü içeren kısmın dışındaysanız, mutlak bir yol elde edersiniz . sys.pathModülü içeren kısmın içindeyseniz, göreceli bir yol elde edersiniz .

Geçerli dizinde bir modül yükleyin ve geçerli dizin varsa değil de sys.path, mutlak bir yol alırsınız.

Geçerli dizinde bir modül yükleyin ve geçerli dizin varsa olduğunu yılında sys.path, akrabası yolunu alırsınız.


"" den modüle giden bir yol varsa, sys.path'in geri kalanı mutlak olduğundan mutlak bir yol kullanılmazsa, göreceli bir yol kullanılacağı anlamına mı gelir ..
goh

4
Geçerli dizinde bir modül yükleyin ve geçerli dizin varsa değil de sys.path, mutlak bir yol alırsınız. Geçerli dizinde bir modül yükleyin ve geçerli dizin varsa olduğunu yılında sys.path, akrabası yolunu alırsınız.
agf

Unutmayın, bu amaçla sys.pathiçermiyor ''.
agf

anladım, ama @agf, / home'dan python /foo/abc.py kullanırsam, sys.path modülünün / home / foo ve mevcut dizinim / home / olduğunu varsayıyorum, neden yazdırıyor dosya bana göreceli bir yol veriyor mu?
goh

55

__file__Python 3.4'ten beri mutlaktır , bir komut dosyasını doğrudan göreceli bir yol kullanarak yürütme durumu dışında:

Modül __file__öznitelikleri (ve ilgili değerler) artık varsayılan olarak her zaman mutlak yollar içermelidir, tek istisna, __main__.__file__bir komut dosyasının doğrudan göreceli bir yol kullanılarak çalıştırılmasıdır. ( Bpo-18416'da Brett Cannon tarafından yapılmıştır .)

Yine de sembolik bağlantıları çözüp çözmediğinden emin değilim.

Göreli bir yol geçme örneği:

$ python script.py

1
Teşekkürler. Bu, izlenmesi zor bir gerçektir!
meawoppl

4
Bu Python 3.4.0 ( Python 3.4.0 (default, Apr 11 2014, 13:05:11) [GCC 4.8.2] on linux) için geçerli değildir . Ve denemelerimde sembolik bağlantılar çözülmedi.
Frozen Flame

@FrozenFlame, 3.4.1 düzeltmezse bugs.python.org'a bildirmekten çekinmeyin .
anatoly techtonik

2
os.path.realpath(__file__)sembolik bağlantıları çözmek için doğru yoldur?
kevinarpe


16

Geç basit örnek:

from os import path, getcwd, chdir

def print_my_path():
    print('cwd:     {}'.format(getcwd()))
    print('__file__:{}'.format(__file__))
    print('abspath: {}'.format(path.abspath(__file__)))

print_my_path()

chdir('..')

print_my_path()

Python-2. * Altında, ikinci çağrı path.abspath(__file__), geçerli dizini temel alarak yanlış bir şekilde belirler :

cwd:     C:\codes\py
__file__:cwd_mayhem.py
abspath: C:\codes\py\cwd_mayhem.py
cwd:     C:\codes
__file__:cwd_mayhem.py
abspath: C:\codes\cwd_mayhem.py

@Techtonik tarafından belirtildiği gibi, Python 3.4+ sürümünde, __file__mutlak bir yol döndürdüğü için bu iyi çalışacaktır .


... için hariç __main__modülü, __file__ olabilecek bir göreli yol.
0xC0000022L

5

@Kindall tarafından sağlanan Guido postasının yardımıyla, standart içe aktarma sürecini modülün her üyesinde bulmaya çalışmak sys.pathve bu arama sonucunda dosyalamak olarak anlayabiliriz (daha fazla ayrıntı PyMOTW Modülleri ve İthalatlarında ). Dolayısıyla, modül mutlak bir yolda bulunuyorsa sys.pathsonuç mutlaktır, ancak sys.pathsonuçta göreli bir yolda yer alıyorsa göreli olur.

Artık site.pybaşlangıç ​​dosyası , başlangıç ​​dosyası sys.pathdışında yalnızca mutlak yolu teslim etmeye özen gösterir ''; bu nedenle, PYTHONPATH'ı ayarlamak dışında başka bir yolla değiştirmezseniz (önek eklemeden önce yolu da mutlak hale getirilir sys.path), her zaman mutlak bir yol elde edersiniz. yol, ancak modüle mevcut dizin üzerinden erişildiğinde.

Şimdi sys.path'i komik bir şekilde kandırırsanız, her şeyi elde edebilirsiniz.

Örneğin , kodun foo.pyiçinde örnek bir modülünüz varsa /tmp/:

import sys
print(sys.path)
print (__file__)

/ Tmp içine girerseniz şunu elde edersiniz:

>>> import foo
['', '/tmp', '/usr/lib/python3.3', ...]
./foo.py

Ne zaman içinde de /home/user, eklersen /tmpsenin PYTHONPATHolsun:

>>> import foo
['', '/tmp', '/usr/lib/python3.3', ...]
/tmp/foo.py

Ekleseniz bile ../../tmpnormalleşecek ve sonuç aynı.

Ancak PYTHONPATHsizi doğrudan kullanmak yerine komik bir yol kullanırsanız, sebep kadar komik bir sonuç alırsınız.

>>> import sys
>>> sys.path.append('../../tmp')
>>> import foo
['', '/usr/lib/python3.3', .... , '../../tmp']
../../tmp/foo.py

Guido, yukarıda belirtilen başlıkta python'un neden tüm girişleri mutlak yollara dönüştürmeye çalışmadığını açıklıyor:

her içe aktarmada getpwd () çağrısı yapmak zorunda kalmak istemiyoruz .... getpwd () nispeten yavaştır ve bazen tamamen başarısız olabilir,

Yolunuz kullanılır Yani olduğu gibi .

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.