Python paketini yerel dizinden yorumlayıcıya aktarın


87

Yerel dizinimde bir paket geliştiriyorum / test ediyorum. Yorumlayıcıya (v2.5) aktarmak istiyorum, ancak sys.path geçerli dizini içermiyor. Şu anda yazıyorum sys.path.insert(0,'.'). Daha iyi bir yol var mı?

Ayrıca,

from . import mypackage

bu hatayla başarısız olur:

ValueError: Attempted relative import in non-package

Bunu nerede okudun "." bir Python modülü müydü?
S. Lot

16
@Lott: Burada açıklanan göreceli bir içe aktarma yolu: docs.python.org/reference/…
projectshave

1
Bu eksiksiz rehbere bakmak isteyebilirsiniz chrisyeh96.github.io/2017/08/08/…
Kevin Zhu

Yanıtlar:


46

Göreli içe from . importaktarmaları yalnızca bir paketin parçası olarak içe aktarılan bir modülden kullanabilirsiniz - betiğiniz veya etkileşimli yorumlayıcınız değildi, bu nedenle elbette ("içe aktardığım paketten içe aktar" anlamına gelir) çalışmıyor. import mypackagesize üst dizini sağlamak kez para cezası olacak mypackageise sys.path(mevcut dizin başardı nasıl uzakta dan sys.pathbilmiyorum? - Eğer site.py garip bir şey varsa, ya da do ...)

Mevcut dizininizi sys.pathoraya geri almak, onu oraya koymaktan daha iyi bir yol değildir.


Ubuntu 8.10 için Python 2.5, yorumlayıcı için sys.path içinde geçerli dizine (boş dize) sahip değildir. Hiçbir şeyi değiştirmedim, bu yüzden bir şekilde o şekilde gönderildi. 3.0'ı yeni yükledim ve sys.path DOES var '' sys.path.
projeler

@projectshave, tamam, Ubuntu'nun şüphesiz nedenleri var! Bunu 8.04'te fark etmedim (şu anda işte kullandığımız şey) ama belki de yeterince dikkat etmiyordum.
Alex Martelli

1
Ben kısmen yanılıyorum. Bir kabuktan çağrılan Python, sys.path içinde geçerli dizine sahiptir. Emacs'tan çağrılan Python, geçerli dizine sahip değil. Garip.
projeler

1
Ah, o zaman Ubuntu'nun aksine sebepleri olan Emacs'tır (bir vim kullanıcısı olarak gerçekten bilmiyorum ;-). Koşullu olarak "." Ekleyebilirsiniz. senin sys.path in, tabii ki orada değil.
Alex Martelli

@Alex Martelli: Çok teşekkür ederim! Eklentimin (Anki için) komut dosyası olarak 'yerel olarak' çalıştırılırken neden farklı bir içe aktarma ifadesine ihtiyaç duyduğunun çözümünü araştırıyor ve arıyorum. Bunun yerine local_launch () yöntemini ekledim ve her şeyi paket klasörünün dışındaki bir komut dosyasından içe aktardığımda / başlattığımda, bir cazibe gibi çalıştı!
Jon Coombs

18

Sys.path belgelerine bakın:

http://docs.python.org/library/sys.html#sys.path

Alıntılamak:

Komut dosyası dizini mevcut değilse (örneğin, yorumlayıcı etkileşimli olarak çağrılırsa veya komut dosyası standart girişten okunursa), yol [0], Python'u ilk önce geçerli dizindeki modülleri aramaya yönlendiren boş dizedir.

Dolayısıyla, python yorumlayıcısını modülünüzü içeren dizinden başlatıyorsanız, sys.path ile çalışmanıza gerek yoktur.

Ayrıca, paketinizi içe aktarmak için şunları yapmanız yeterlidir:

import mypackage

Paketi içeren dizin zaten sys.path içinde olduğundan, düzgün çalışması gerekir.


1
Çalışma ortamının başka bir yerinde benzer bir dosya adı varsa başarısız olur.
JAR.JAR.beans

@ JAR.JAR.beans geçerli çalışma dizini ilk şey olmalıdır, sys.pathbu nedenle dosyalar çalışma ortamında başka herhangi bir yerde dosyalardan önce bulunmalıdır.
SpoonMeiser

3
İyi bir nokta. Yani, dosyayı yerel dizinden çalıştırırsak. Başka bir klasör olması durumunda ve sys.path'e bir değişiklik yapılması gerektiğinde - bu, sys.path.insert(0, new_path)yerine sys.path.append(new_path).
JAR.JAR.beans

15

Değiştirilmemiş bir python betiğini çalıştırarak kütüphaneleri belirli bir yerel dizinden içe aktarmak istiyorsanız, PYTHONPATHortam değişkenini ayarlayabilirsiniz - örneğin bash:

export PYTHONPATH=/home/user/my_libs
python myscript.py

Yalnızca geçerli çalışma dizininden içe aktarılmasını istiyorsanız, .gösterimi kullanın :

export PYTHONPATH=.
python myscript.py

PYTHONPATH'ın dışa aktarılması, python dışında programlamayı içerir (örn. Bash'da). Ek olarak, docs.python.org/3/using/cmdline.html'de " varsayılan arama yolunun kuruluma bağlı olduğu" açıkça belirtilmiştir .
ilias iliadis

13

Basit tutun:

 try:
     from . import mymodule     # "myapp" case
 except:
     import mymodule            # "__main__" case

7
Bu çözümü beğendim, en basit olanı. Geriye kalan tek soru, ithalatları uygularken "bunu yapmanın tek yolu" kuralının neden isteğe bağlı kabul edildiğidir ... Cidden, paketleri beyan etmenin ve düzenlemenin tüm dezavantajları olan yaklaşık 15 yolu vardır
Léo Germond

5

Çalıştırmanın basit bir yolu, betiğinizi python'un -mbayrağını kullanarak ana dizinden çalıştırmaktır , örn python -m packagename.scriptname. Açıkçası bu durumda __init__.pydizininizi bir pakete dönüştürmek için bir dosyaya ihtiyacınız var .


5

Bir paketin içinde setup.py varsa , onu kurmak daha iyidir

pip install -e .

3

Kullanmak sys.pathzaten mevcut dizini içermelidir.

Deneyin:

import .

veya:

from . import sth

ancak bu iyi bir uygulama olmayabilir, öyleyse neden sadece kullanmayalım:

import mypackage

5
<İmport mypackage> ile ilgili sorun, paketi global python env'den yükleyecek olmasıdır, paketi / dosyayı yerel klasörden yükleyebilir, ancak aynı zamanda çalışma ortamındaki başka bir rastgele mypackge de yükleyebilir.
JAR.JAR.beans

3

Partiye biraz geç kaldım ama benim için işe yarayan şey buydu:

>>> import sys
>>> sys.path.insert(0, '')

Görünüşe göre boş bir dizge varsa, Python bunun geçerli dizine bakması gerektiğini bilir. sys.pathBu hataya neden olan boş dizeye sahip değildim .


1

Kullandığım pathlibBenim için bir paket ve @maninthecomputer cevap olarak çalışmalarını modülü vermedi yüklemeden kaçınmak istediği gibi benim sistem yoluna benim modül dizini eklemek için

import sys
from pathlib import Path

cwd = str(Path(__file__).parent)
sys.path.insert(0, cwd)
from my_module import my_function
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.