Python'da göreli bir yoldan içe aktarma


Yanıtlar:


150

Kasım 2014 DÜZENLEME (3 yıl sonra):

Python 2.6 ve 3.x, bilgisayar korsanlığı yapmaktan kaçınabileceğiniz uygun göreli içe aktarmaları destekler. Bu yöntemle, mutlak bir içe aktarma yerine göreli bir içe aktarma elde ettiğinizi bilirsiniz . "..", üstümdeki dizine git anlamına gelir:

from ..Common import Common

Bir uyarı olarak, bu yalnızca python'unuzu paketin dışından bir modül olarak çalıştırırsanız işe yarar . Örneğin:

python -m Proj

Orijinal hacky yolu

Bu yöntem, paketinizi aslında hiçbir zaman 'yüklemediğiniz' bazı durumlarda hala yaygın olarak kullanılmaktadır. Örneğin, Django kullanıcıları arasında popülerdir.

Sys.path'inize Common / ekleyebilirsiniz (python'un bir şeyleri içe aktarmak için baktığı yolların listesi):

import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'Common'))
import Common

os.path.dirname(__file__) sadece size mevcut python dosyanızın bulunduğu dizini verir ve sonra dizine 'Common /' gider ve modülü 'Common' alırız.


2
Python modülleri yolunu manuel olarak değiştirmeyin, yalnızca hızlı hackler için olabilir. Dağıtımları, kurulum araçlarını vb. Kullanarak Python paket yönetimini öğrenmek, genellikle bunun gibi sorunları çözecek gerekli bir beceridir.
Sascha Gottfried

1
@SaschaGottfried tamamen aynı fikirdedir, ancak dağıtılabilir bir paket oluşturmuyorsanız, muhtemelen önemli olmayacaktır. Örneğin, Django'da uygulamanızı dağıtımlarla asla gerçekten kurmazsınız, bu nedenle yukarıdaki yöntem kolay bir hacklemedir. Ama yine de, bugünlerde ne yapacağımla ilgili cevabı düzenledim.
Dave

36
Doğru teknik hakkında vaaz vermek yerine asıl soruyu yanıtladığınız için teşekkürler. Göreli ithalat yapmak için pek çok iyi neden var.
kır faresi

birden fazla seviyeye nasıl çıkarsın?
jxramos

10
bir seviye daha yukarı çıkmak için her seviye için ek bir nokta kullanın. @jxramos ex: from ...myfilegider../../myfile
WattsInABox

11

Yeterince komik, aynı problemle karşılaştım ve bu işi şu şekilde alıyorum:

linux komutu ile birleştirerek ln, her şeyi çok daha basit hale getirebiliriz:

1. cd Proj/Client
2. ln -s ../Common ./

3. cd Proj/Server
4. ln -s ../Common ./

Ve, şimdi ithalat istiyorsanız some_stuffdosyadan: Proj/Common/Common.pydosyanızın içine: Proj/Client/Client.py, aynen böyle:

# in Proj/Client/Client.py
from Common.Common import some_stuff

Ve aynı şey için Proj/Serverde geçerlidir , Ayrıca setup.pysüreç için de geçerlidir , burada tartışılan aynı soru , umarım yardımcı olur!


10

Göreli içe aktarma yapmayın.

Gönderen PEP8 :

Paket içi ithalatlar için göreli ithalatlar kesinlikle tavsiye edilmiyor.

Tüm kodunuzu tek bir süper pakete (yani "uygulamam") koyun ve istemci, sunucu ve ortak kod için alt paketler kullanın.

Güncelleme: " Python 2.6 ve 3.x uygun göreli içe aktarmaları destekler (...) ". Daha fazla ayrıntı için Dave'in yanıtlarına bakın.


1
İstemcinin ve sunucunun sonuna ' if __name__ == "__main__":' satırından sonra bazı kodlar eklediğinizi hayal edin . Yani, onları bağımsız komut dosyaları olarak kullanabilmek istiyorsunuz. Nasıl düzgün yapılır? Bence bu, desteklenmesi gereken çok yaygın bir kullanım durumu. Neden cesareti kırılıyor?
Jabba

85
"Bunu yapma" nın "nasıl yaparım ..." sorusu için kabul edilen yanıt olmasına şaşırdım (pekala, Rails <g> dışında.) Bunu yapmak için ara sıra nedenler olabilir. Dave'in önerdiğine benzer bir çözüm kullanıyorum.
Tom Wilson

1
@TomWilson: Saf "yapma" cevabı değil. Aşağıda "bu şekilde yap" var.
Michał Šrajer

2
Birisi Numpy'deki çocuklara söylemeli! TON göreceli ithalat kullanıyorlar!
Austin

12
Bu cevap Python'un güncel sürümleri için geçerli değildir. Alıntılanan kısım artık PEP 8'de bulunmayacaktır. Günümüzde şu şekilde okunmaktadır: "açık göreli içe
aktarmalar,

9

Göreli bir ithalat yapmak kesinlikle sorun değil! İşte benim yaptığım küçük şeyler:

#first change the cwd to the script path
scriptPath = os.path.realpath(os.path.dirname(sys.argv[0]))
os.chdir(scriptPath)

#append the relative location you want to import from
sys.path.append("../common")

#import your module stored in '../common'
import common.py

1
Ama sys.argv [0] 'nın gerçekte nereye işaret ettiğini bilseniz iyi olur - bu (büyük olasılıkla) python'u başlattığınızda içinde bulunduğunuz dizin değildir.
CarlH

Bu, birçok tuzağı olan hızlı bir hack'tir. Ancak soru daha da iyi değildi.
Sascha Gottfried

1
Bu açıkça yazılmış, ancak Dave'in cevabındaki orijinal hack daha iyi çünkü __file__mevcut dosyadan uygun ilişkiyi elde etmek için kullanıyor
John Neuhaus

4

Varsayılan içe aktarma yöntemi, PYTHONPATH'tan zaten "göreli" dir. PYTHONPATH varsayılan olarak, orijinal kaynak dosyanın klasörüyle birlikte bazı sistem kitaplıkları içindir. Bir modülü çalıştırmak için -m ile çalıştırırsanız, mevcut dizin PYTHONPATH'a eklenir. Dolayısıyla, programınızın giriş noktası import Common.CommonProj'in içindeyse, kullanımı hem Server.py hem de Client.py içinde çalışmalıdır.

Göreceli bir içe aktarma yapmayın. İstediğin gibi çalışmayacak.


1
Eğer bu doğruysa, neden en iyi cevaplar bunu söylemiyor? Bu işe yarayacak mı çalışmayacak mı?
Anonim
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.