ファイル間でグローバル変数を使用していますか?


209

グローバル変数の動作について少し混乱しています。約50個のファイルを持つ大規模なプロジェクトがあり、それらすべてのファイルのグローバル変数を定義する必要があります。

私がしたことは、main.py次のようにプロジェクトファイルでそれらを定義することでした:

# ../myproject/main.py

# Define global myList
global myList
myList = []

# Imports
import subfile

# Do something
subfile.stuff()
print(myList[0])

私が使用しようとしているmyList中でsubfile.py、以下のように、

# ../myproject/subfile.py

# Save "hey" into myList
def stuff():
    globals()["myList"].append("hey")

私が試した別の方法ですが、どちらも機能しませんでした

# ../myproject/main.py

# Import globfile    
import globfile

# Save myList into globfile
globfile.myList = []

# Import subfile
import subfile

# Do something
subfile.stuff()
print(globfile.myList[0])

そして、subfile.py私はこれを持っていました:

# ../myproject/subfile.py

# Import globfile
import globfile

# Save "hey" into myList
def stuff():
    globfile.myList.append("hey")

しかし、再び、それはうまくいきませんでした。これをどのように実装すればよいですか?2つのファイルがお互いを本当に認識していない場合(サブファイルがメインを認識していない場合)、そのように機能しないことは理解していますが、io書き込みまたはピクルを使用しないと、その方法を考えることができません。やりたくない。


実際、あなたの2番目のアプローチは私にとってはうまく機能します。main.pyは「hey」を正しく出力します。「うまくいかなかった」ということで、あなたが私にもっと具体的に教えてくれませんか?
ロディオン2012年

@rodion:インポートサイクル-サブファイル内のコードがグロブファイルをインポートしようとします。グロブファイル内のコード自体がインポートされます
jsbueno

1
NameError: name 'myList' is not definedmain.py行からprint(globfile.myList[0])

回答:


320

問題はmyListから定義しmain.pyたものですsubfile.pyが、使用する必要があります。この問題を解決するためのクリーンな方法を次に示しますsettings.py。すべてのグローバルをファイルに移動します。このファイルを呼び出します。このファイルは、グローバルの定義と初期化を担当します。

# settings.py

def init():
    global myList
    myList = []

次に、subfileグローバルをインポートできます。

# subfile.py

import settings

def stuff():
    settings.myList.append('hey')

subfileは呼び出さないことに注意してください。そのinit()タスクは次のものに属していmain.pyます。

# main.py

import settings
import subfile

settings.init()          # Call only once
subfile.stuff()         # Do stuff with global var
print settings.myList[0] # Check the result

このようにして、グローバル変数を複数回初期化することを避けながら目的を達成します。


41
私は一般的なアプローチが好きですが、全部ではありませんinit()。モジュールは最初にインポートされたときにのみ評価されるため、モジュールの本体でこれらの変数を初期化しても問題ありません。
Kirk Strauser

19
+1カーク:同意する。ただし、私のアプローチでは、メインプログラムが開始する前に他のモジュールがglobals.myListを変更するケースを防ぎます。
Hai Vu

2
あなたはそれを組み込み名であるグローバル以外のものと呼ぶべきです。PyLintは警告を出します:「組み込みの「グローバル」の再定義(
redefined

ありがとう。このファイル構造を使用してEclipse PyDevに表示される「インポートから未定義の変数」エラーを削除する方法(つまり、settings.pyからグローバル変数をインポートする方法)PyDevのエラー無効にする必要がありましたが、これは理想的ではありません。
フランクダーノンコート2015

@FranckDernoncourtごめんなさい、私はEclipseを使っていないので、あなたよりも無知です。
Hai Vu

94

モジュール間でのグローバル変数の共有に関するPythonのドキュメントを参照してください。

単一のプログラム内のモジュール間で情報を共有する標準的な方法は、特別なモジュール(しばしばconfigまたはcfgと呼ばれる)を作成することです。

config.py:

x = 0   # Default value of the 'x' configuration setting

アプリケーションのすべてのモジュールに構成モジュールをインポートします。その後、モジュールはグローバル名として使用可能になります。

main.py:

import config
print (config.x)

または

from config import x
print (x)

一般に、from modulename import * は使用しないください。これを行うと、インポーターの名前空間が乱雑になり、リンターが未定義の名前を検出することがはるかに困難になります。


1
命の恩人-ちょうどそのリンクのために!
toonarmycaptain

4
これは、受け入れられた答えよりもクリーンなアプローチのようです。
JoeyC

2
xを使用して設定することはできません。from config import x使用するのはimport config
Yariv

1
最も簡単な解決策!ありがとう
user1297406

22

Pythonのグローバル変数は「モジュール」変数と考えることができます。そのため、Cの従来の「グローバル変数」よりもはるかに便利です。

グローバル変数は実際にはモジュールで定義されて__dict__おり、モジュールの属性としてそのモジュールの外部からアクセスできます。

したがって、あなたの例では:

# ../myproject/main.py

# Define global myList
# global myList  - there is no "global" declaration at module level. Just inside
# function and methods
myList = []

# Imports
import subfile

# Do something
subfile.stuff()
print(myList[0])

そして:

# ../myproject/subfile.py

# Save "hey" into myList
def stuff():
     # You have to make the module main available for the 
     # code here.
     # Placing the import inside the function body will
     # usually avoid import cycles - 
     # unless you happen to call this function from 
     # either main or subfile's body (i.e. not from inside a function or method)
     import main
     main.mylist.append("hey")

1
うわー、通常、2つのファイルが相互にインポートされて無限ループになることを想定しています。
Nikhil VJ 2018

2
ha一見するとそのように見えますね。def stuff()で何が起きるかは、ファイルが読み込まれたときにインポートが実行されないことです。stuff()関数が呼び出されたときにのみ実行されます。メインから始めて、サブファイルをインポートしてからsubfile.stuff()を呼び出し、メインをインポートします...ループなし、メインで一度インポートするだけです。インポートサイクルに関するsubfile.pyの例のメモを参照してください。
ジョン

11

使用する from your_file import *て問題を解決する必要があります。グローバルに利用できるようにすべてを定義します(もちろん、インポートのローカル変数を除く)。

例えば:

##test.py:

from pytest import *

print hello_world

そして:

##pytest.py

hello_world="hello world!"

4
あなたがそのような変数に割り当てた場合を除き
jsbueno

5
import *参照を明示的に(混乱させないように)するために、私は個人的に使用することを絶対に避けています。さらに、実際にすべての「*」参照を任意のモジュールで実際に使用したことがありますか?
ThorSummoner 2014

19
インポートしないでください*。グローバル変数は同期されなくなります。各モジュールは独自のコピーを受け取ります。あるファイルで変数を変更しても、別のファイルには反映されません。それはまたに対して警告されますdocs.python.org/2/faq/…ます
Isa Hassen

8

Hai Vuの回答はうまくいきました。コメントは1つだけです:

他のモジュールでグローバルを使用していて、グローバルを動的に設定する場合は、グローバル変数を設定した後、他のモジュールをインポートするように注意してください。次に例を示します。

# settings.py
def init(arg):
    global myList
    myList = []
    mylist.append(arg)


# subfile.py
import settings

def print():
    settings.myList[0]


# main.py
import settings
settings.init("1st")     # global init before used in other imported modules
                         # Or else they will be undefined

import subfile    
subfile.print()          # global usage

4

2回目の試行は完全に機能し、グローバルに使用できるようにしたい変数名を処理するための本当に良い方法です。しかし、最後の行に名前エラーがあります。これがどうあるべきかです:

# ../myproject/main.py

# Import globfile    
import globfile

# Save myList into globfile
globfile.myList = []

# Import subfile
import subfile

# Do something
subfile.stuff()
print(globfile.myList[0])

最後の行を参照してください?myListはサブファイルではなく、globfileのattrです。これはあなたが望むように動作します。

マイク

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