Python: modülü proje hiyerarşisinde aynı seviyedeki başka bir dizinden içe aktarın


89

Her türden örnek ve benzeri soruları gördüm, ancak senaryomla tam olarak eşleşen bir örnek bulamıyorum. Bunu soran bir aptal gibi hissediyorum çünkü pek çok benzer soru var, ancak bunu "doğru" çalıştırmayı başaramıyorum. İşte benim projem:

user_management  (package)
        |
        |------- __init__.py
        |
        |------- Modules/
        |           |
        |           |----- __init__.py
        |           |----- LDAPManager.py
        |           |----- PasswordManager.py
        |
        |------- Scripts/
        |           |
        |           |----- __init__.py
        |           |----- CreateUser.py
        |           |----- FindUser.py

"CreateUser.py" yi ana user_management dizinine taşırsam, "import Modules.LDAPManager"LDAPManager.py'yi içe aktarmak için kolayca kullanabilirim --- bu çalışır. Yapamadığım şey (yapmak istediğim), CreateUser.py'yi Scripts alt klasöründe tutmak ve LDAPManager.py'yi içe aktarmak. Bunu kullanarak başarmayı umuyordum "import user_management.Modules.LDAPManager.py". Bu çalışmıyor. Kısacası, Python dosyalarının hiyerarşide kolayca daha derinlemesine bakmasını sağlayabilirim, ancak bir dizini yukarı ve aşağıya referans veren bir Python betiği alamıyorum.

Sorunumu şu şekilde çözebileceğimi unutmayın:

sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import Modules.LDAPManager as LDAPManager

Bunun kötü bir uygulama olduğunu ve cesaretin kırıldığını duydum.

Komut dosyalarındaki dosyalar doğrudan çalıştırılmak üzere tasarlanmıştır ( Komut dosyalarındaki init .py gerekli midir?). Bu durumda, CreateUser.py'yi -m bayrağıyla çalıştırmam gerektiğini okudum. Bununla ilgili bazı varyasyonları denedim ve CreateUser.py'nin LDAPManager.py'yi tanımasını sağlayamıyorum.

Yanıtlar:


67

Ben taşırsanız CreateUser.pyana user_management dizinine, kolayca kullanabilirsiniz: import Modules.LDAPManagerithalat LDAPManager.py --- bu işleri.

Lütfen yapma . Bu şekilde LDAPManagerkullandığı modül CreateUserolacak değil diğer ithalat yoluyla ithal aynı olması. Bu, modülde küresel bir durum olduğunda veya asitleme / ayırma sırasında sorunlar yaratabilir. Yalnızca modül aynı dizinde olduğu için çalışan içe aktarmalardan kaçının .

Bir paket yapınız olduğunda şunlardan birini yapmalısınız:

  • Eğer ie göreli ithalat kullanın CreateUser.pyiçindedir Scripts/:

     from ..Modules import LDAPManager
    

    Bu o Not oldu (Not geçmiş gergin) cesaretini PEP 8 piton eski sürümleri çok iyi onlara destek vermedi çünkü ancak bu sorun yıllar önce çözüldü. Mevcut PEP 8 versiyonu etmez mutlak ithalat kabul edilebilir bir alternatif olarak göstermektedir. Aslında onları paketlerin içinde seviyorum .

  • Tüm paket adını ( CreateUser.pyinç Scripts/) kullanarak mutlak içe aktarmaları kullanın :

     from user_management.Modules import LDAPManager
    

İşe İkincisi için Amacıyla paket user_managementiçine monte edilmelidir PYTHONPATH. Geliştirme sırasında IDE'yi, herhangi bir yere manuel olarak çağrı eklemek zorunda kalmadan bunun gerçekleşmesi için yapılandırabilirsiniz sys.path.append.

Ayrıca Scripts/bir alt paket olmasını garip buluyorum . Çünkü gerçek bir kurulumda user_managementmodül site-packages, lib/dizinde bulunan (işletim sisteminizde kitaplıkları kurmak için hangi dizin kullanılırsa kullanılsın) altına kurulur, komut dosyaları ise bir bin/dizin altına kurulmalıdır (hangisi işletim sisteminiz için yürütülebilir dosyalar içeriyorsa).

Aslına bakarsan Script/, altının bile olmamasına inanıyorum user_management. İle aynı seviyede olmalıdır user_management. Bu şekilde kullanmak zorunda değilsiniz-m , ancak paketin bulunabileceğinden emin olmalısınız (bu yine IDE'yi yapılandırmak, paketi doğru yüklemek veya PYTHONPATH=. python Scripts/CreateUser.pykomut dosyalarını doğru yolla başlatmak için kullanmaktır ).


Özetle, hiyerarşi ı kullanırsınız geçerli:

user_management  (package)
        |
        |------- __init__.py
        |
        |------- Modules/
        |           |
        |           |----- __init__.py
        |           |----- LDAPManager.py
        |           |----- PasswordManager.py
        |

 Scripts/  (*not* a package)
        |  
        |----- CreateUser.py
        |----- FindUser.py

Ardından, modülleri içe aktarmak için mutlak içe aktarma kodu CreateUser.pyve FindUser.pykullanması gerekir:

from user_management.Modules import LDAPManager

Kurulum sırasında , modülleri bulabilmeleri için yürütülebilir dosyalar için dizinin içindeki ve komut dosyalarının içinde bir user_managementyerde sona erdiğinden emin olun PYTHONPATH. Gelişimi sırasında ya IDE yapılandırması güvenmek ya da başlatmak CreateUser.pyekleyerek Scripts/için üst dizini PYTHONPATH(ben hem içeren dizini demek user_managementve Scripts):

PYTHONPATH=/the/parent/directory python Scripts/CreateUser.py

Ya da PYTHONPATHher seferinde bunu belirtmeniz gerekmeyecek şekilde global olarak değiştirebilirsiniz . Unix işletim sistemlerinde (linux, Mac OS X vb.) PYTHONPATHHarici değişkeni tanımlamak için kabuk komut dosyalarından birini değiştirebilirsiniz , Windows'ta çevresel değişken ayarlarını değiştirmeniz gerekir.


Ek Sana python2 kullanıyorsanız, o emin koyarak örtük nispi ithalat önlemek için yapmak daha iyidir, inanıyorum:

from __future__ import absolute_import

modüllerinizin en üstünde. Bu şekilde import X her zaman üst düzey modülü içe aktarmak anlamına gelir Xve asla X.pyaynı dizinde bulunan dosyayı içe aktarmayı denemeyecektir (eğer bu dizin içinde değilse PYTHONPATH). Bu şekilde, göreceli bir içe aktarma yapmanın tek yolu , daha iyi olan ( açık, örtükten daha iyi olan) açık sözdizimini (the from . import X) kullanmaktır .

Bu, "düzmece" örtük göreli içe aktarmaları asla kullanmamanızı sağlar, çünkü bunlar bir ImportErrorşeylerin yanlış olduğuna dair açık bir sinyal oluşturacaktır. Aksi takdirde, düşündüğünüz gibi olmayan bir modül kullanabilirsiniz.


Eğer göreli ithalat kullanıyorsanız, sen yürütmek gerekirpython -m user_management.Scripts.CreateUser
mononoke

14

Python 2.5'ten itibaren kullanabilirsiniz

from ..Modules import LDAPManager

Öncü dönem sizi hiyerarşinizde bir seviye "yukarı" çıkarır.

İçe aktarmalar için paket içi referanslarla ilgili Python belgelerine bakın .


3

"Kök" bölümünde __init__.pyayrıca bir

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

bu her iki modülü de ithal edilebilir hale getirmelidir.


0

Ben de aynı sorunlarla karşılaştım. Bunu çözmek için kullandım export PYTHONPATH="$PWD". Bununla birlikte, bu durumda, Scriptsaşağıdakilere bağlı olarak dizininizdeki içe aktarmaları değiştirmeniz gerekecektir :

Durum 1: user_managementDizindeyseniz, modülü içe aktarmak scriptsiçin bu stili kullanmalısınız from Modules import LDAPManager.

Durum 2: Eğer dışarı değilseniz user_managementgibi 1 düzeyinde main, senin scriptsbu stili kullanmalıdır from user_management.Modules import LDAPManagerithalat modülleri.

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.