Python 2.5 kullanıyorum.
Bu benim klasör ağacım:
ptdraft/
nib.py
simulations/
life/
life.py
(Ayrıca her klasörde __init__.py
var, okunabilirlik için burada belirtilmemiş)
nib
modülünü life
modülünün içinden nasıl içe aktarırım? Sys.path ile uğraşmadan yapmak mümkün olduğunu umuyorum.
Not: Çalışmakta olan ana modül ptdraft
klasöründedir.
Sorunun, modülün bir üst dizinde olması ya da onun gibi bir şeyle ilgili olmadığı görülüyor.
ptdraft
öğesini içeren dizini PYTHONPATH konumuna eklemeniz gerekir.
import nib
'in sizinle birlikte çalıştığını söylediniz, bu muhtemelen PYTHONPATH'e ptdraft
' in kendisini (üst değil) eklediğiniz anlamına gelir.
Göreli ithalat kullanabilirsiniz (python> = 2.5):
from ... import nib
(Python 2.5’teki Yenilikler) PEP 328: Mutlak ve Göreli İthalat
DÜZENLE: başka bir nokta ekledi '.' iki paket yukarı gitmek
Göreli ithalat (from .. import mymodule
'da olduğu gibi) yalnızca bir paket içerisinde çalışır. Geçerli modülünüzün ana dizinindeki 'mymodule' dosyasını almak 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__
niteliği her zaman verilmez. os.path.abspath(__file__)
kullanmak yerine şimdi geçerli dosyanın dosya adını (ve yolunu) almak için inspect modülünü kullanmayı önerdim
Kardeş paketlerden yapılan ithalatla ilgili soruya da benzer bir cevap gönderdim. Bunu görebilirsiniz burada . Aşağıdakiler Python 3.6.5, (Anaconda, conda 4.5.1), Windows 10 makinesiyle test edilmiştir.
Sorudakiyle aynı klasör yapısını kabul ediyorum
.
└── ptdraft
├── __init__.py
├── nib.py
└── simulations
├── __init__.py
└── life
├── __init__.py
└── life.py
.
kök klasörünü çağırıyorum ve benim durumumda C:\tmp\test_imports
konumunda bulunuyor.
setup.py
içeriğini basit olabilir
from setuptools import setup, find_packages
setup(name='myproject', version='1.0', packages=find_packages())
Temel olarak "any" setup.py işe yarar. Bu sadece minimal bir çalışma örneğidir.
Sanal ortamlara aşina iseniz, birini etkinleştirin ve bir sonraki adıma geçin. Sanal ortamların kullanımı değil kesinlikle gerekli, ancak onlar gerçekten uzun vadede size yardımcı olacaktır (1'den fazla projeniz olduğunda) devam eden ..). En temel adımlar: (root klasöründe çalıştır)
python -m venv venv
. /venv/bin/activate
(Linux) veya ./venv/Scripts/activate
(Win)Bu konuda daha fazla bilgi edinmek için, sadece "python virtual env tutorial" veya benzeri bir Google çıksın. Muhtemelen asla oluşturmak, etkinleştirmek ve devre dışı bırakmaktan başka bir komuta ihtiyacınız yoktur.
Sanal bir ortam oluşturduktan ve etkinleştirdikten sonra, konsolunuz sanal ortamın adını parantez içinde vermelidir.
PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>
myproject
kullanarak en üst seviye paket pip
yükleyin. İşin püf noktası, kurulumu yaparken -e
bayrağını kullanmaktır. Bu şekilde düzenlenebilir bir durumda kurulur ve .py dosyalarında yapılan tüm düzenlemeler otomatik olarak kurulu pakete dahil edilir.
Kök dizinde, çalıştır
pip install -e .
(noktayı not edin, "geçerli dizin" anlamına gelir)
Ayrıca, pip freeze
kullanarak da yüklendiğini görebilirsiniz.
(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
mainfolder
ekleyerek içe aktarınBu örnekte, mainfolder
, ptdraft
olacaktır. Bu, diğer modül adlarıyla (python standart kütüphanesinden veya 3. parti modüllerden) çarpışmalarla karşılaşmamanız avantajına sahiptir.
def function_from_nib():
print('I am the return value from function_from_nib!')
from ptdraft.nib import function_from_nib
if __== '__main__':
function_from_nib()
(venv) PS C:\tmp\test_imports> python .\ptdraft\simulations\life\life.py
I am the return value from function_from_nib!
Modül klasörünüzü PYTHONPATH'e eklemek işe yaramadıysa, programınızdaki Python yorumlayıcısının modülleri aradığı sys.path listesini değiştirebilirsiniz. almak için python belgeleri diyor ki:
spam adında bir modül alındığında, tercüman önce bu adı taşıyan yerleşik bir modülü arar. Bulunamadıysa, sys.path değişkeni tarafından verilen dizinler listesinde spam.py adlı bir dosyayı arar. sys.path bu konumlardan başlatıldı:
- giriş komut dosyasını içeren dizin (veya geçerli dizini).
- PYTHONPATH (Shell değişkeni PATH ile aynı sözdizimine sahip bir dizin adı listesi).
- yüklemeye bağlı varsayılan.
Başlattıktan sonra Python programları sys.path öğesini değiştirebilir. Çalışmakta olan betiği içeren dizin, standart kütüphane yolunun önüne, arama yolunun başına yerleştirilir. Bu, kütüphane dizininde aynı isimde modüller yerine, o 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
İşletim sistemine bağlı yolu sys.path içinde listelenen "modül arama yolu" nda kullanabilirsiniz. Böylece aşağıdaki gibi ana dizini kolayca ekleyebilirsiniz
import sys
sys.path.insert(0,'..')
Üst-üst dizin eklemek istiyorsanız,
sys.path.insert(0,'../..')
Python 2 hakkında fazla bir şey bilmiyorum.
Python 3'te, ana klasör aşağıdaki gibi eklenebilir:
import sys
sys.path.append('..')
... ve bir tanesi bundan modülleri içe aktarabilir
İşte basit bir cevap bu yüzden nasıl çalıştığını görebilirsiniz, küçük ve çapraz platform.
Yalnızca yerleşik modülleri kullanır (os
name__, sys
ve inspect
name__) bu nedenle çalışması gerekir
herhangi bir işletim sisteminde (OS) çünkü Python bunun için tasarlandı.
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
ile değiştirin,getsourcefile
(satır 3) başlangıcına inspect.
ekleyin ve ilk satırı kaldırın.
- bununla birlikte, bu modülün tamamını ithal eder, böylece daha fazla zamana, hafızaya ve kaynağa ihtiyaç duyabilir.
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.
Bir Yığın Taşması cevabından bir örnek kullanır Akımın yolunu nasıl bulurum?
Python'da dosya çalıştırıldı mı? çalışan kodun kaynağını (dosya adı) yerleşik bir araçla bulmak için.
from inspect import getsourcefile from os.path import abspath
Daha sonra, kaynak dosyayı nerede bulmak isterseniz, sadece şunu kullanın:
abspath(getsourcefile(lambda:0))
Kodum, sys.path
dosyasına bir dosya yolu ekler, python yolu listesi
çünkü bu Python'un bu klasörden modülleri içe aktarmasına izin veriyor.
Koddaki bir modülü içe aktardıktan sonra, sys.path.pop(0)
dosyasını yeni bir satırda çalıştırmak iyi bir fikirdir
bu eklenen klasör, içe aktarılan başka bir modülle aynı ada sahip bir modüle sahipse
daha sonra programda. Diğer yolları değil, içe aktarmadan önce eklenen liste öğesini kaldırmanız gerekir.
Programınız diğer modülleri içe aktarmazsa, dosya yolunu silmemek güvenlidir, çünkü
bir program sona erdikten sonra (veya Python Kabuğunu yeniden başlattıktan sonra), sys.path
'da yapılan düzenlemeler kaybolur.
Cevabım, çalışan dosya yolunu/dosya adını almak için __file__
değişkenini kullanmıyor
kodu, çünkü buradaki kullanıcılar sık sık güvenilmez olarak tanımlamıştır. Kullanmamalısın
başkaları tarafından kullanılan programlarda üst klasörden modüller almak için.
Çalışmadığı bazı örnekler (alıntı b Yığın Taşması sorusu):
• o olamaz bazı platformlarda bulundu • o bazen tam dosya yolu değil
py2exe
__file__
özelliğine sahip değildir, ancak bir geçici çözüm var- IDLE'den
execute()
ile çalıştırdığınızda,__file__
niteliği yoktur.- OS X 10.6 nerede
NameError: global name '__file__' is not defined
alırım
İşte sys.path içine ana 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))
Benim için üst dizine erişim 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 adını döndürür.
Aslında, bence Python proje mimarisi, alt dizindeki hiç kimsenin ana dizindeki herhangi bir modülü kullanmayacağı ş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 ana dizin eklemektir.
import sys sys.path.append('../')
__init__.py
dosyalarının bulunduğu bir paket ortamında olmadığınızda, pathlib kütüphanesi (> = Python 3.4 dahil) ana dizinin yolunu PYTHONPATH'e eklemeyi çok özlü ve sezgisel hale getirir:
import sys
from pathlib import Path
sys.path.append(str(Path('.').absolute().parent))
Yukarıda belirtilen çözümler de iyidir. Bu sorunun başka bir çözümü
Üst düzey dizinden bir şey almak istiyorsanız. Sonra,
from ...module_name import *
Ayrıca, herhangi bir modülü ana dizinden almak istiyorsanız. Sonra,
from ..module_name import *
Ayrıca, herhangi bir modülü ana dizinden almak istiyorsanız. Sonra,
from ...module_name.another_module import *
Bu şekilde, istediğiniz herhangi bir yöntemi içe aktarabilirsiniz.
önceki cevapla aynı stilde - ancak 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
Bir betiği betiğin ana dizininden almak için aşağıdaki yöntemlerin işe yaradığını buldum. Örnekte, env.py
içindeki işlevleri app.db
paketinden içe aktarmak istiyorum.
.
└── 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)
Kütüphanelerle çalışın. Nib adında bir kütüphane yapın, bunu setup.py kullanarak kurun, site paketlerinde kalmasına izin verin ve sorunlarınız çözüldü. Yaptığınız her şeyi tek bir pakette yapmak zorunda değilsiniz. Parçalara ayır.
Bir Linux sisteminde "life" klasöründen nib.py dosyasına yumuşak bir link oluşturabilirsiniz. Ardından, basitçe aşağıdaki gibi içe aktarabilirsiniz:
import nib