Üst klasörden modülleri içe aktarma


624

Python 2.5 kullanıyorum.

Bu benim klasör ağacım:

ptdraft/
  nib.py
  simulations/
    life/
      life.py

(Bende var __init__.py her klasörde, okunabilirlik için burada atlanmıştır)

nibModülü içeriden nasıl alırımlife ? Sys.path ile uğraşmadan yapmanın mümkün olduğunu umuyorum.

Not: Çalıştırılmakta olan ana modül ptdraftklasördedir.


1
PYTHONPATH ayarınız nedir?
S.Lott

2
Ross: Oraya baktım. Bunun hakkında ne yapayım? Zaten bir __init__.py. S.Lott: Nasıl kontrol edeceğimi bilmiyorum ...
Ram Rachum

4
echo $ PYTHONPATH kabuktan; ithalat sistemi; Python içinden sys.path yazdırabilirsiniz. docs.python.org/tutorial/…
S.Lott

@FlipMcF Google kabarcıklı bir arama motorudur, bu nedenle bu sonucun sizin için oldukça yüksek olması önemli değildir. Çok daha önemli olan, kabarcıklanmayan arama motoru DuckDuckGo'nun da bunu çok yüksek sırada tutmasıdır.
ArtOfWarfare

3
Hepsini sys.pathveya PYTHONPATHcevapları atlamayı ve np8'in mükemmel yanıtını kontrol etmenizi şiddetle tavsiye ederim . Evet, uzun bir okuma. Evet, çok fazla iş gibi görünüyor. Ancak problemi doğru ve temiz bir şekilde çözen tek cevap bu.
Aran-Fey

Yanıtlar:


118

Sorun, modülün bir üst dizinde olması veya bunun gibi bir şeyle ilgili olmadığı anlaşılıyor.

İçeren dizini ptdraftPYTHONPATH dizinine eklemeniz gerekir

Sizinle import nibçalıştığını söylediniz, bu muhtemelen ptdraftPYTHONPATH'a kendisini (ebeveynini değil) eklediğiniz anlamına gelir .


15
Asla tekrar kullanılmayacak çok fazla paketle çalışıyorsanız, pythonpath'e her şeyi eklemek iyi bir çözüm değildir.
Jason Cheng

@JasonCheng: O zaman neden paketler ?
Davis Herring

7
Benim için bu cevap işe yaradı. Ancak, daha açık hale getirmek için, prosedür import sysve sonrasys.path.append("..\<parent_folder>")
BCJuan

603

Göreli içe aktarmaları kullanabilirsiniz (python> = 2.5):

from ... import nib

(Python 2.5'teki Yenilikler) PEP 328: Mutlak ve Göreli İthalatlar

EDIT : başka bir nokta ekledi '.' iki paket yukarı çıkmak


177
ValueError: Attempted relative import in non-package
endolith

18
@ endolith: Bir pakette olmalısınız, yani bir init .py dosyanız olmalıdır.
kirbyfan64sos

31
Üst düzey paketin ötesinde göreli içe aktarma girişimi
Kullanıcı

291
Daha da net olmak gerekirse, bir __init__.pydosyaya ihtiyacınız var .
kara deniz

17
__init__.pyEkleme yapmanız gereken tek şey olmadığından , aşağıdaki cevaba da bakınız : stackoverflow.com/questions/11536764/…
Ben Farmer

286

Göreli ithalat (olduğu gibi from .. import mymodule) sadece bir pakette çalışır. Mevcut modülünüzün üst dizinindeki 'mymodule' dosyasını içe aktarmak için:

import os,sys,inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0,parentdir) 

import mymodule

edit : __file__özellik her zaman verilmez. Kullanmak yerine os.path.abspath(__file__)şimdi geçerli dosyanın dosya adını (ve yolunu) almak için inspect modülünü kullanmanızı önerdim


97
biraz daha kısa bir şey:sys.path.insert(1, os.path.join(sys.path[0], '..'))
JHolta

8
Eklemek yerine sys.path.append () önlemek için herhangi bir neden?
Tyler

2
@Tyler - O zaman başka bir yerde olması önemli olabilir parentdir, ancak zaten belirtilen yollardan birinde, sys.path'mymodule' adında başka bir modül var. Listenin parentdirilk öğesi olarak eklenmesi, sys.pathmodülün parentdiriçe aktarılacağını garanti eder .
Remi

5
@JHolta Paketlerle ilgilenmiyorsanız, sizinki en iyi çözümdür.
Jonathon Reinhart

5
@JHolta harika bir fikir. sys.path.insert(1, os.path.realpath(os.path.pardir))çalışır.
SpeedCoder5

177

Kardeş paketlerden yapılan ithalatla ilgili soruya da benzer bir cevap gönderdim. Burada görebilirsiniz .

sys.pathKesmeksizin çözüm

özet

  • Kodu bir klasöre sarın (ör. packaged_stuff)
  • Setuptools.setup () yönteminisetup.py kullandığınız create komut dosyasını kullanın .
  • Pip ile paketi düzenlenebilir durumda yükleyin pip install -e <myproject_folder>
  • Kullanarak içe aktar from packaged_stuff.modulename import function_name

Kurmak

Sorudakiyle aynı klasör yapısını varsayıyorum

.
└── ptdraft
    ├── __init__.py
    ├── nib.py
    └── simulations
        ├── __init__.py
        └── life
            ├── __init__.py
            └── life.py

.Kök klasörü çağırıyorum ve benim durumumda yer alıyor C:\tmp\test_imports.

adımlar

1) setup.pyKök klasöre a ekleyin

Kutunun içeriği setup.pybasitçe

from setuptools import setup, find_packages

setup(name='myproject', version='1.0', packages=find_packages())

Temelde "herhangi" setup.pyişe yarayacaktı. Bu sadece minimal bir çalışma örneğidir.

2) Sanal bir ortam kullanın

Sanal ortamlara aşina iseniz, birini etkinleştirin ve sonraki adıma geçin. Sanal ortamların kullanılması kesinlikle gerekli değildir , ancak uzun vadede size gerçekten yardımcı olacaktır (1'den fazla projeniz devam ederken ..). En temel adımlar (kök klasörde çalıştır)

  • Sanal env oluştur
    • python -m venv venv
  • Sanal env'yi etkinleştir
    • . /venv/bin/activate(Linux) veya ./venv/Scripts/activate(Kazan)

Bu konuda daha fazla bilgi edinmek için, sadece "python virtualenv tutorial" veya benzeri Google'ı kullanın. Muhtemelen oluşturma, etkinleştirme ve devre dışı bırakma dışında başka komutlara ihtiyacınız yoktur.

Bir sanal ortam oluşturup etkinleştirdikten sonra, konsolunuz parantez içinde sanal ortamın adını vermelidir

PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>

3) pip projenizi düzenlenebilir durumda yükleyin

myprojectKullanarak üst düzey paketinizi kurun pip. Hile, -eyükleme yaparken bayrağı kullanmaktır . Bu şekilde düzenlenebilir bir duruma yüklenir ve .py dosyalarında yapılan tüm düzenlemeler otomatik olarak yüklü pakete dahil edilir.

Kök dizinde çalıştırın

pip install -e . (noktaya dikkat edin, "geçerli dizin" anlamına gelir)

Ayrıca şunu kullanarak yüklendiğini görebilirsiniz: pip freeze

(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///C:/tmp/test_imports
Installing collected packages: myproject
  Running setup.py develop for myproject
Successfully installed myproject
(venv) PS C:\tmp\test_imports> pip freeze
myproject==1.0

4) mainfolderHer ithalata ekleyerek ithalat

Bu örnekte, mainfolderolurdu ptdraft. Bunun avantajı, diğer modül adlarıyla (python standart kitaplığından veya 3. taraf modüllerinden) ad çakışmalarına girmemenizdir.


Örnek Kullanım

nib.py

def function_from_nib():
    print('I am the return value from function_from_nib!')

life.py

from ptdraft.nib import function_from_nib

if __name__ == '__main__':
    function_from_nib()

Koşu life.py

(venv) PS C:\tmp\test_imports> python .\ptdraft\simulations\life\life.py
I am the return value from function_from_nib!

1
Bu neden işe yarıyor? Bir şekilde perde arkasındaki PYTHONPATH'ı değiştiriyor mu?
Homero Esmeraldo

2
Ayrıca, bu neden sys.path yaklaşımını kullanmaktan daha iyi veya daha zarif?
Homero Esmeraldo

5
@HomeroBarrocasSEsmeraldo Güzel sorular. PYTHONPATH env var dokunulmamış. Bu , zaten açık olan ve kodun genellikle son kullanıcılar tarafından yükleneceği site paketlerinesys.path yüklenir. Bu, sys.pathkorsanlardan daha iyidir (ve bu yol korsanlığı kategorisine PYTHONPATH kullanmayı da ekleyebilirsiniz), çünkü geliştirme kodunun diğer kullanıcılar için olduğu gibi davranması gerektiği anlamına gelir. Bunun aksine, yol değişiklikleri kullanılırken içe aktarma ifadeleri farklı bir şekilde çözülür.
wim

5
Bu şimdiye kadar okuduğum en iyi çözüm. Bu, geçerli dizininize bir bağlantı oluşturur, böylece koddaki tüm güncellemeler doğrudan çalışma dizininize yansıtılır. Bu girdiyi silmeniz gerekiyorsa, yumurta dosyasını manuel olarak silin ve girdiyi dağıtım paketlerine (pip kullandıysanız site paketleri) kolay kurulumdan kaldırın.
Rakshit Kothari

2
neden python ithalat baş ağrısını daha da karmaşık hale getiriyor? Bir kurulum dosyası, bir sanal env, bir pip yüklemesi mi yazmalıyız? Aman Tanrım!
Emerson Xu

68

Sys.path içinde listelenen "modül arama yolu" nda OS'ye bağlı yolu kullanabilirsiniz . Böylece aşağıdaki gibi üst dizini kolayca ekleyebilirsiniz

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

Üst-üst dizin eklemek istiyorsanız,

sys.path.insert(0,'../..')

Bu hem python 2 hem de 3'te çalışır.


6
Bu, geçerli dizine göredir, ana komut dosyasını içeren dizine bile gerek yoktur.
Davis Herring

57

Modül klasörünüzü PYTHONPATH öğesine eklemek işe yaramadıysa, programınızdaki Python yorumlayıcısının içe aktarılacak modülleri aradığı sys.path listesini değiştirebilirsiniz , python belgeleri şöyle diyor:

Spam adlı bir modül içe aktarıldığında, yorumlayıcı önce bu ada sahip yerleşik bir modül arar. Bulunamazsa, sys.path değişkeni tarafından verilen dizinler listesinde spam.py adlı bir dosyayı arar . sys.path şu konumlardan başlatılır:

  • girdi komut dosyasını içeren dizin (veya geçerli dizin).
  • PYTHONPATH (kabuk değişkeni PATH ile aynı sözdizimine sahip dizin adlarının listesi).
  • yüklemeye bağlı varsayılan.

Başlatma işleminden sonra, Python programları sys.path dosyasını değiştirebilir . Çalıştırılan komut dosyasını içeren dizin, arama yolunun başına, standart kitaplık yolunun önüne yerleştirilir. Bu, kütüphane dizininde aynı ada sahip modüller yerine bu dizindeki komut dosyalarının yükleneceği anlamına gelir. Değişim amaçlanmadıkça bu bir hatadır.

Bunu bilerek, programınızda aşağıdakileri yapabilirsiniz:

import sys
# Add the ptdraft folder path to the sys.path list
sys.path.append('/path/to/ptdraft/')

# Now you can import your module
from ptdraft import nib
# Or just
import ptdraft

6
Cevabınız iyi, ancak her zaman işe yaramayabilir ve çok taşınabilir değildir. Program yeni bir konuma taşındıysa, /path/to/ptdraftdüzenlenmelidir. Dosyanın geçerli dizinini çalıştıran ve ana klasörden bu şekilde içe aktaran çözümler vardır.
Edward

@Edward bu teknikler nelerdir?
Shuklaswag

1
@Shuklaswag, örneğin, stackoverflow.com/questions/714063/… .
Edward

50

Python 2 hakkında fazla bir şey bilmiyorum
. Python 3'te, üst klasör aşağıdaki gibi eklenebilir:

import sys 
sys.path.append('..')

... ve sonra modüller


13
Bu yalnızca geçerli çalışma dizininiz, söz '..'konusu modülün bulunduğu dizine götürecek şekilde çalışıyorsa çalışır .
user5359531

31

İşte basit bir cevap, böylece nasıl çalıştığını görebilirsiniz, küçük ve çapraz platform.
Sadece (modüllerin dahili kullanır os, sysveinspect ) bu nedenle
Python bunun için tasarlandığından herhangi bir işletim sisteminde (OS) çalışmalıdır .

Yanıt için daha kısa kod - daha az satır ve değişken

from inspect import getsourcefile
import os.path as path, sys
current_dir = path.dirname(path.abspath(getsourcefile(lambda:0)))
sys.path.insert(0, current_dir[:current_dir.rfind(path.sep)])
import my_module  # Replace "my_module" here with the module name.
sys.path.pop(0)

Bundan daha az satır için ikinci satırı import os.path as path, sys, inspect,
ekleme inspect.başındagetsourcefile (hat 3) ve birinci satırı kaldırın.
- ancak bu tüm modülü içe aktarır, böylece daha fazla zaman, bellek ve kaynak gerekebilir.

Cevabımın kodu ( daha uzun versiyon )

from inspect import getsourcefile
import os.path
import sys

current_path = os.path.abspath(getsourcefile(lambda:0))
current_dir = os.path.dirname(current_path)
parent_dir = current_dir[:current_dir.rfind(os.path.sep)]

sys.path.insert(0, parent_dir)

import my_module  # Replace "my_module" here with the module name.

Yığın Taşması yanıtından bir örnek kullanır Python'da geçerli
yürütülen dosyanın yolunu nasıl alabilirim ?
yerleşik bir araçla çalışan kodun kaynağını (dosya adını) bulmak için.

from inspect import getsourcefile  
from os.path import abspath  

Sonra, kaynak dosyayı bulmak istediğiniz her yerde kullanın:

abspath(getsourcefile(lambda:0))

Kodum şuraya bir dosya yolu ekliyor: sys.path ,Kodum
, Python'un bu klasörden modülleri almasına izin verdiği python yolu listesine .

Koddaki bir modülü içe aktardıktan sonra, bu eklenen klasör, daha sonra programda içe aktarılan başka bir modülle aynı ada sahip bir modüle sahip olduğunda sys.path.pop(0)yeni bir satırda çalıştırmak iyi bir fikirdir . İçe aktarmadan önce eklenen liste öğesini kaldırmanız gerekir, diğer yolları kaldırmanız gerekir. Programınız diğer modülleri içe aktarmazsa, dosya yolunu silmemek güvenlidir çünkü



bir program bittikten (veya Python kabuğunu yeniden başlattıktan sonra), yapılan tüm değişiklikler sys.pathkaybolacağı .

Dosya adı değişkeni hakkında notlar

Cevabım __file__değişkeni çalışan
kodun dosya yolunu / dosya adını almak için kullanmıyor, çünkü buradaki kullanıcılar genellikle güvenilmez olarak tanımladılar . Diğer kişiler tarafından kullanılan programlarda üst klasörden modül almak
için kullanmamalısınız .

Çalışmadığı bazı örnekler ( Bu Yığın Taşması sorusundan alıntı ):

• o edilemez bazı platformlarda • bazen üzerinde bulunan tam dosya yolu değil

  • py2exebir __file__niteliği yok, ancak bir geçici çözüm var
  • IDLE'den çalıştırdığınızda execute()hiçbir __file__özellik yok
  • OS X 10.6'yı nereden edinebilirim NameError: global name '__file__' is not defined

1
Bunu yaptım ve sys.path.pop(0)istenen modülü içe aktardıktan hemen sonra yeni yol girişini kaldırdım . Ancak, daha sonraki ithalat hala bu yere gitti. Örneğin app/config, app/toolsve var app/submodule/config. Gönderen submodule, app/içe aktarmak için eklemek tools, sonra kaldırmak app/ve almaya çalışın config, ama app/configyerine alıyorum app/submodule/config.
user5359531

toolsİthalatlarından birinin de configana şirketten ithal edildiğini anladım . Daha sonra sys.path.pop(0); import configiçeri girmeye çalıştığımda submodule, almayı beklediğimde app/submodule/config, aslında alıyordum app/config. Açıkçası Python, aslında sys.pathbu adla eşleşen bir modülü kontrol etmek yerine aynı ada sahip bir modülün önbelleğe alınmış bir sürümünü döndürür . sys.pathbu durumda doğru bir şekilde değiştiriliyordu, Python zaten aynı adlı modül zaten yüklenmiş olduğundan kontrol etmiyordu.
user5359531


5.3.1'deki bazı yararlı bilgiler . Modül önbellek üzerinde dokümantasyon sayfasından : İçe aktarma sırasında modül adı içinde aranır sys.modules ... sys.modules yazılabilir olduğunu. Bir anahtarın silinmesi, adlandırılan modülün önbellek girişini geçersiz kılarak Python'un bir sonraki içe aktarma işleminde yeniden arama yapmasına neden olur. ... Ancak, modül nesnesine bir başvuru tutarsanız, önbelleğini geçersiz kılar ve sonra yeniden içe aktarırsanız, iki nesne farklı olacaktır. Buna karşılık, importlib.reload()modül içeriğini yeniden kullanacak ve yeniden başlatacak ...
Edward

Hatta daha kısa: os.path.realpath(getsourcefile(lambda:0) + "/../.."). Geçerli kaynak dosyaya iki üst dizin sembolü eklenir. Ben kullanmadım os.path.sepolarak getsourcefilekullanarak bir dize döndürür oldu /bile Windows üzerinde. realpathüst dizini veren tam yoldan (bu durumda dosya adı ve sonra geçerli dizin) iki dizin girdisinin kaldırılmasına dikkat eder.
Coburn

28

İşte sys.path içine üst dizini içeren daha genel bir çözüm (benim için çalışıyor):

import os.path, sys
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))

import os, sys\n sys.path.insert(0,os.path.pardir) aynı şey, ama üzücü :) (yorumlarda satır besleme yok)
Anti Veeranna

@antiveeranna, eğer kullanırsanız os.path.pardir, ebeveynin gerçek yolunu sys.path.insert()
almayacaksınız

1
Bu yanıt, StackOverflow kullanıcılarının sıklıkla bahsettiği gibi, güvenilir__file__ olamayacak değişkeni kullanır (her zaman tam dosya yolu değildir, her işletim sisteminde çalışmaz vb.). Cevabı dahil etmeyecek şekilde değiştirmek daha az soruna ve çapraz uyumlu hale gelmesine neden olacaktır. Daha fazla bilgi için bkz. Stackoverflow.com/a/33532002/3787376 .
Edward

23

Komut dosyasının üst dizininden bir paketi almak için aşağıdaki yolu buldum. Örnekte, ben de fonksiyonlarını ithal etmek istiyorum env.pyden app.dbpaketin.

.
└── my_application
    └── alembic
        └── env.py
    └── app
        ├── __init__.py
        └── db
import os
import sys
currentdir = os.path.dirname(os.path.realpath(__file__))
parentdir = os.path.dirname(currentdir)
sys.path.append(parentdir)

Yani, güzel bir tek katlı:sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
juzzlin

Değiştirmek sys.pathgenellikle kötü bir fikirdir. Kütüphanenizin diğer kodlara erişebilmesi için bir yol ( ör . PYTHONPATH) Gerekir (ya da gerçekten bir kütüphane değildir); sadece her zaman kullanın!
Davis Herring

14

Yukarıda belirtilen çözümler de gayet iyi. Bu soruna başka bir çözüm

Üst düzey dizinden bir şey almak istiyorsanız. Sonra,

from ...module_name import *

Ayrıca, üst dizinden herhangi bir modülü içe aktarmak istiyorsanız. Sonra,

from ..module_name import *

Ayrıca, üst dizinden herhangi bir modülü içe aktarmak istiyorsanız. Sonra,

from ...module_name.another_module import *

Bu şekilde, isterseniz herhangi bir yöntemi içe aktarabilirsiniz.


6
Bu olması gerektiği gibi görünüyor, ancak bir nedenden dolayı bu sys.path.appendyukarıdaki hack'lerle aynı şekilde çalışmıyor ve libimi böyle ithal edemiyorum. Google'a başlamadan önce ilk yapmayı denediğim bu :) Tamam, buValueError: attempted relative import beyond top-level package
juzzlin

10

Benim için üst dizine erişmek için en kısa ve en sevdiğim oneliner:

sys.path.append(os.path.dirname(os.getcwd()))

veya:

sys.path.insert(1, os.path.dirname(os.getcwd()))

os.getcwd () geçerli çalışma dizininin adını, os.path.dirname (dizin_adı) iletilen dizinin dizin adını döndürür.

Aslında, bence Python proje mimarisi, alt dizindeki hiç bir modülün üst dizindeki herhangi bir modülü kullanamayacağı şekilde yapılmalıdır. Böyle bir şey olursa, proje ağacı hakkında yeniden düşünmeye değer.

Başka bir yol da PYTHONPATH sistem ortam değişkenine üst dizin eklemektir.


2
Projeyi yeniden yapılandırma
zorunluluğundan

bu ebeveyni almaz, güncel olur
Ricky Levi

9

Jupyter Not Defterinde

Bir Jupyter Notebook'da çalıştığınız sürece, bu kısa çözüm yararlı olabilir:

%cd ..
import nib

Bir __init__.pydosya olmadan bile çalışır .

Linux ve Windows 7'de Anaconda3 ile test ettim.


2
%cd -İçe aktarma işleminden sonra eklemek mantıklı olmaz mı , bu nedenle not defterinin geçerli dizini değişmeden kalır.
Dror


5

__init__.pyDosyaları içeren bir paket ortamında olmadığında , pathlib kitaplığı (> = Python 3.4 ile birlikte verilir), üst dizinin yolunu PYTHONPATH'a eklemeyi çok özlü ve sezgisel hale getirir:

import sys
from pathlib import Path
sys.path.append(str(Path('.').absolute().parent))

Bu sorunu atlatmak için init .py kullanmak mümkün mü?
Yapay

4

geçmiş yanıtla aynı tarzda - ama daha az satırda: P

import os,sys
parentdir = os.path.dirname(__file__)
sys.path.insert(0,parentdir)

dosya, çalıştığınız konumu döndürür


Benim için dosya dosya adı olmadan dahil yolu. Ben "ipy dosyaadı.py" kullanarak çalıştırın.
Curtis Yallop

Merhaba @ Yukarıdaki örnekte python dosyasının içinde bulunduğu dosyayı (şu anda bulunduğumuz) içeren dizini ekliyoruz. Dosya adıyla os.path.dirname çağrısı dosyanın yolunu döndürmeli ve dosyaya değil, yola THAT ekliyoruz - HTH's :-)
YFP

__File__ dosyasının her zaman yolu ve dosyayı içerdiğini varsayıyorsunuz. Bazen yalnızca yolu olmayan dosya adını içerir.
Curtis Yallop

@CurtisYallop - hiç de efendim, dosyanın dosya adı olduğunu varsayalım ve dosya yolunu almak için os.path.dirname () kullanıyorum. Bunun işe yaramadığına bir örnek var mı? Üreme adımları
YFP

1
@CurtisYallop - Hayır, değilim! Ben şunu söylüyorum: print / _ / file / _ / yukarıdaki "file.py" örneğindeki dosya adını verecektir . Eğer garip bir yerden arıyorsanız ve o ilişkisel istiyorsanız o zaman kolayca çalışma dir os modülü - Jeez aracılığıyla bulabilirsiniz!
YFP

1

Kütüphanelerle çalışın. Nib adlı bir kitaplık oluşturun, setup.py dosyasını kullanarak yükleyin, site paketlerinde kalmasına izin verin ve sorunlarınız çözüldü. Yaptığınız her şeyi tek bir pakette doldurmanız gerekmez. Parçalara ayırın.


1
Fikriniz iyi, ancak bazı insanlar modüllerini kodlarıyla birlikte paketlemek isteyebilir - belki de taşınabilir hale getirmek ve modüllerini site-packagesfarklı bir bilgisayarda her çalıştırdıklarında koymak zorunda kalmazlar .
Edward

0

Linux sisteminde, "life" klasöründen nib.py dosyasına yumuşak bir bağlantı oluşturabilirsiniz. Ardından, aşağıdaki gibi içe aktarabilirsiniz:

import nib
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.