Global değişkenleri tanımlamak için __init__.py kullanabilir miyim?


130

Bir paketin tüm alt modüllerinde bulunması gereken bir sabit tanımlamak istiyorum. En iyi yerin __init__.pykök paketin dosyasında olacağını düşündüm . Ama bunu nasıl yapacağımı bilmiyorum. Birkaç alt paketim olduğunu ve her birinde birkaç modül olduğunu varsayalım. Bu değişkene bu modüllerden nasıl erişebilirim?

Tabii ki, bu tamamen yanlışsa ve daha iyi bir alternatif varsa, bunu bilmek isterim.

Yanıtlar:


196

Onları içeri koyabilmelisin __init__.py. Bu her zaman yapılır.

mypackage/__init__.py:

MY_CONSTANT = 42

mypackage/mymodule.py:

from mypackage import MY_CONSTANT
print "my constant is", MY_CONSTANT

Ardından, mymodule'ü içe aktarın:

>>> from mypackage import mymodule
my constant is 42

Yine de, sabitleriniz varsa, onları ayrı bir modüle (sabitler.py, config.py, ...) koymak mantıklı olacaktır (muhtemelen en iyi uygulamalar) ve sonra bunları paket ad alanında istiyorsanız, içe aktarın onlar.

mypackage/__init__.py:

from mypackage.constants import *

Yine de bu, sabitleri paket modüllerinin ad alanlarına otomatik olarak dahil etmez. Paketindeki modüllerin her hala gelen açıkça ya ithalat sabitleri zorunda kalacak mypackageya dan mypackage.constants.


19
Bu kabul edilen cevap olmalıydı. Python 2.5 veya üstü ile çalışıyorsanız, burada açıklandığı gibi açık bir göreli içe aktarma da kullanabilirsiniz : from . import MY_CONSTANT
ThatAintWorking

ikinci yol sadece sabitler için çalışmıyor mu? aynı değişkene referans yerine her alt from mypackage.constants import *MY_CONSTANT
modülün

@hardmooth: Tam olarak değil. Değerler referans olarak kopyalanır, yani MY_CONSTANTmodüllerden herhangi birinde mutasyona uğrayacak olursanız, her yerde değişecektir. MY_CONSTANTModüllerden herhangi birini yeniden atarsanız , bu yalnızca o modülü etkiler. Niyetiniz buysa, özniteliğe göre referans vermelisiniz, yani mypackage.constants.MY_CONSTANT.
Jason R. Coombs

7
İçe Örneğin Tek yakalamak olduğunu mymodule.pyiçinde __init__.pyönce MY_CONSTANT = 42ithal zaman çünkü başarısız olacağını mymodule.py MY_CONSTANThenüz tanımlanmamıştır. Öyleyse MY_CONSTANT = 42yukarı hareket import mymodule
etmelisin

değişken nasıl? Sabitleri değil, değişkenleri soruyor. Python paket içindeki değişkeni nasıl ele alır? Paketin içindeki değişken değiştirilmişse ne olur?
TomSawyer

31

Bunu yapamazsın. Sabitlerinizi açıkça her bir modülün ad alanına aktarmanız gerekecektir. Bunu başarmanın en iyi yolu, sabitlerinizi bir "yapılandırma" modülünde tanımlamak ve ihtiyaç duyduğunuz her yere aktarmaktır:

# mypackage/config.py
MY_CONST = 17

# mypackage/main.py
from mypackage.config import *

Evet, bir yapılandırma dosyası istediğim şey. Ben düşündüm ki init .py iyi bir yer olurdu. Çözümünüz standart uygulama gibi geliyor. Bu mu?
Andrei Vajna II

1
İyi bir nokta. Sorunun sabitlerin tüm paket modüllerinin ad alanına otomatik olarak yerleştirilmesi olduğunu fark etmemiştim .
Jason R. Coombs

Ancak bir komut dosyası config.py'yi her içe aktardığında, içindeki kod çalıştırılır. Config.py içindeki kod yalnızca bir kez çalıştırılacaksa ne önerirsiniz? Config.py içinde bir settings.json dosyası okuyorum ve config.py'yi her içe aktardığımda açmak () istemiyorum.
Augiwan

@UGS Python böyle çalışmıyor. Her modül yalnızca bir kez yürütülür. İkinci kez içe aktarıldığında, modül zaten önbelleğe alınmıştır sys.modules.
Ferdinand Beyer

@FerdinandBeyer Oops! Config.py dosyasını aynı komut dosyasından değil birkaç komut dosyasından içe aktardığımı söylemeyi unuttum. A.py'nin config.py & b.py'yi içe aktardığını ve b.py'nin config.py'yi içe aktardığını varsayalım. Config.py içindeki kodun yalnızca bir kez çalıştırıldığından emin olmanın mümkün olup olmadığını merak ediyordum.
Augiwan

2

Global değişkenleri her yerden tanımlayabilirsiniz, ancak bu gerçekten kötü bir fikirdir. __builtin__modülü içe aktarın ve bu modüllere nitelikleri değiştirin veya ekleyin ve birdenbire yeni yerleşik sabitlere veya işlevlere sahip olursunuz. Aslında, uygulamam gettext'i yüklediğinde, hiçbir şey içe aktarmadan tüm modüllerimde _ () işlevini alıyorum. Yani bu mümkündür, ancak elbette yalnızca Uygulama tipi projeler için, yeniden kullanılabilir paketler veya modüller için değil.

Ve sanırım hiç kimse bu uygulamayı önermeyecek. Bir ad alanının nesi var? Söz konusu uygulama sürüm modülüne sahiptir, böylece "global" değişkenlere sahip olabilirim version.VERSION, version.PACKAGE_NAMEvb.


0

Sabitlerin bir config.ini dosyası kullanılarak kullanılabileceğini ve configparser kitaplığı kullanılarak komut dosyasında ayrıştırılabileceğini eklemek istedim. Bu şekilde, birden çok durum için sabitlere sahip olabilirsiniz. Örneğin, iki ayrı url isteği için parametre sabitleriniz varsa, bunları şu şekilde etiketleyin:

mymodule/config.ini
[request0]
conn = 'admin@localhost'
pass = 'admin'
...

[request1]
conn = 'barney@localhost'
pass = 'dinosaur'
...

Python web sitesindeki belgeleri çok yararlı buldum. Python 2 ile 3 arasında herhangi bir fark olup olmadığından emin değilim, bu yüzden her ikisinin de bağlantıları:

Python 3 için: https://docs.python.org/3/library/configparser.html#module-configparser

Python 2 için: https://docs.python.org/2/library/configparser.html#module-configparser

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.