__init__.pyを使用してグローバル変数を定義できますか?


130

パッケージのすべてのサブモジュールで使用できる定数を定義したいと思います。一番いい場所は__init__.pyルートパッケージのファイルにあると思いました。しかし、私はこれを行う方法がわかりません。いくつかのサブパッケージがあり、それぞれにいくつかのモジュールがあるとします。これらのモジュールからその変数にアクセスするにはどうすればよいですか?

もちろん、これが完全に間違っていて、より良い代替案がある場合は、それを知りたいのですが。

回答:


196

それらをに入れることができるはず__init__.pyです。これは常に行われます。

mypackage/__init__.py

MY_CONSTANT = 42

mypackage/mymodule.py

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

次に、mymoduleをインポートします。

>>> from mypackage import mymodule
my constant is 42

それでも、定数がある場合は、それらを別のモジュール(constants.py、config.pyなど)に配置するのが妥当(おそらくベストプラクティス)であり、次にパッケージの名前空間に定数をインポートする必要があります。それら。

mypackage/__init__.py

from mypackage.constants import *

それでも、パッケージモジュールの名前空間に定数が自動的に含まれるわけではありません。パッケージ内の各モジュールは、定数を明示的に、mypackageまたはから明示的にインポートする必要がありmypackage.constantsます。


19
これは受け入れられるべき答えでした。あなたは、Python 2.5以上を使用している場合は説明しているようにも同様に、明示的な相対インポートを使用することができ、ここでfrom . import MY_CONSTANT
ThatAintWorking

2番目の方法は定数に対してのみ機能しませんか?同じ変数への参照ではなく、すべてのサブモジュールにのfrom mypackage.constants import *コピーを配置MY_CONSTANTします
hardmooth

@hardmooth:厳密には違います。値は参照によってコピーされるためMY_CONSTANT、モジュールのいずれかで変更を行うと、どこでも変更されます。MY_CONSTANTモジュールのいずれかに再割り当てした場合、そのモジュールにのみ影響します。それがあなたの意図であるならば、あなたは属性によって参照しなければなりません、すなわちmypackage.constants.MY_CONSTANT
Jason R. Coombs

7
この例の問題点の1つは、インポートがまだ定義されていないためにmymodule.py__init__.py以前にインポートMY_CONSTANT = 42すると失敗することmymodule.py MY_CONSTANTです。したがって、MY_CONSTANT = 42上に移動する必要がありますimport mymodule
markmnl 2017年

変数はどうですか?定数ではなく、変数について尋ねています。Pythonはパッケージ内の変数をどのように扱いますか?パッケージ内の変数が変更された場合はどうなりますか?
TomSawyer

31

それをしてはいけない。個々のモジュールの名前空間に定数を明示的にインポートする必要があります。これを達成するための最良の方法は、「c​​onfig」モジュールで定数を定義し、それを必要なすべての場所にインポートすることです。

# mypackage/config.py
MY_CONST = 17

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

ええ、設定ファイルは私が欲しいものです。私はちょうどinit .pyが良い場所だと思いました。あなたのソリューションは標準的な練習のように聞こえます。それは...ですか?
Andrei Vajna II

1
いい視点ね。質問がすべてのパッケージモジュールの名前空間に定数を自動的に配置することであることに気づきませんでした。
Jason R. Coombs

しかし、スクリプトがconfig.pyをインポートするたびに、内部のコードが実行されます。config.py内のコードを1回だけ実行する場合、何をお勧めしますか?config.py内のsettings.jsonファイルを読んでいて、config.pyをインポートするたびにopen()したくないとしましょう。
Augiwan 2014

@UGSこれはPythonの動作方法ではありません。すべてのモジュールは1回だけ実行されます。2回目のインポート時には、モジュールはすでににキャッシュされていsys.modulesます。
Ferdinand Beyer 14

@FerdinandBeyerおっと!同じスクリプトではなく、いくつかのスクリプトからconfig.pyをインポートしていることを忘れていました。a.pyがconfig.py&b.pyをインポートし、b.pyがconfig.pyをインポートするとします。config.py内のコードが1回だけ実行されることを確認できるかどうか疑問に思っていました。
Augiwan 2014

2

グローバル変数はどこからでも定義できますが、これは非常に悪い考えです。__builtin__モジュールをインポートして、このモジュールの属性を変更または追加すると、突然、新しい組み込み定数または関数ができます。実際、アプリケーションがgettextをインストールすると、何もインポートせずにすべてのモジュールで_()関数を取得します。したがって、これは可能ですが、もちろん、再利用可能なパッケージやモジュールではなく、アプリケーションタイプのプロジェクトでのみ可能です。

とにかく、誰もこの方法を推奨することはないでしょう。名前空間の何が問題になっていますか?上記のアプリケーションにはバージョンモジュールがあるためversion.VERSIONversion.PACKAGE_NAMEなどの「グローバル」変数を使用できます。


0

定数を追加するには、config.iniファイルを使用して定数を使用し、configparserライブラリを使用してスクリプトで解析することができます。この方法では、複数の状況で定数を使用できます。たとえば、2つの別々のURLリクエストのパラメータ定数がある場合は、次のようにラベルを付けます。

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

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

PythonのWebサイトにあるドキュメントは非常に役に立ちました。Python 2と3の間に違いがあるかどうかはわかりませんので、ここに両方へのリンクがあります:

Python 3の場合:https : //docs.python.org/3/library/configparser.html#module-configparser

Python 2の場合:https : //docs.python.org/2/library/configparser.html#module-configparser

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.