2012-10-23 16 views
85

Ich bin etwas verwirrt darüber, wie die globalen Variablen funktionieren. Ich habe ein großes Projekt mit ungefähr 50 Dateien und ich muss globale Variablen für all diese Dateien definieren.Globale Variablen zwischen Dateien verwenden?

Was ich tat, war sie in meinen Projekten main.py Datei definieren, wie folgend:

# ../myproject/main.py 

# Define global myList 
global myList 
myList = [] 

# Imports 
import subfile 

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

Ich versuche myList in subfile.py zu verwenden, wie folgende

# ../myproject/subfile.py 

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

Eine andere Art, wie ich versucht, aber hat auch nicht funktioniert

# ../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]) 

Und innen subfile.py Ich hatte dies:

# ../myproject/subfile.py 

# Import globfile 
import globfile 

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

Aber noch einmal, es hat nicht funktioniert. Wie soll ich das umsetzen? Ich verstehe, dass es so nicht funktionieren kann, wenn sich die beiden Dateien nicht wirklich kennen (naja Subdatei weiß man nicht), aber ich kann mir nicht vorstellen, wie ich es machen soll, ohne io schreiben oder beizen zu müssen, was Ich will es nicht tun.

+0

Eigentlich funktioniert Ihr zweiter Ansatz gut für mich. main.py druckt "hey" korrekt aus. Kannst du genauer sagen, was du mir durch "es hat nicht funktioniert"? – rodion

+0

@rodion: Importieren von Zyklen - der Code in der Subdatei versucht, globfile zu importieren, die sich in sich selbst importiert – jsbueno

+1

'NameError: Name 'myList' ist nicht definiert 'aus' main.py' Zeile 'print (globfile.myList [0 ]) ' –

Antwort

156

Das Problem ist, dass Sie myList von main.py definiert, aber subfile.py muss es benutzen. Hier ist ein sauberer Weg, um dieses Problem zu lösen: Verschieben Sie alle Globals in eine Datei, ich rufe diese Datei settings.py.Diese Datei ist verantwortlich für Globals definieren und initialisieren sie:

# settings.py 

def init(): 
    global myList 
    myList = [] 

Als nächstes Ihre Unterdatei kann Globals importieren:

# subfile.py 

import settings 

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

Beachten Sie, dass Unterdatei nicht init nicht nennen() - diese Aufgabe zur Haupt gehört. 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 

Auf diese Weise erreichen Sie Ihr Ziel, während vermeiden globale Variablen mehr als einmal initialisiert wird.

+15

Ich mag den allgemeinen Ansatz, aber nicht das Ganze 'init()' Zeug. Module werden nur beim ersten Import ausgewertet. Daher ist es vollkommen in Ordnung, diese Variablen im Hauptteil des Moduls zu initialisieren. –

+8

+1 Kirk: Ich stimme zu. Mein Ansatz verhindert jedoch den Fall, dass andere Module globals.myList ändern, bevor das Hauptprogramm gestartet wird. –

+2

Sie sollten es etwas anderes als globals nennen, was ein eingebauter Name ist. PyLint gibt die Warnung: "Neudefinieren von eingebauten Globalen" (redefined-builtin) " – twasbrillig

12

Mit from your_file import * sollten Sie Ihre Probleme beheben. Es definiert alles so, dass es global verfügbar ist (mit Ausnahme der lokalen Variablen bei den Importen natürlich).

zum Beispiel:

##test.py: 

from pytest import * 

print hello_world 

und:

##pytest.py 

hello_world="hello world!" 
+3

Außer wenn Sie eine solche Variable zuweisen – jsbueno

+2

Ich persönlich vermeide die Verwendung von' Import * 'um jeden Preis, so dass Referenzen sind explizit (und nicht verwirrend), Außerdem, wann immer Sie tatsächlich alle" '*' verwendet haben "Referenzen in irgendeinem Modul? – ThorSummoner

+8

NICHT importieren *. Ihre globalen Variablen bleiben nicht länger synchron. Jedes Modul erhält eine eigene Kopie. Das Ändern der Variablen in einer Datei spiegelt sich nicht in einer anderen wider. Es wird auch davor gewarnt in https://docs.python.org/2/faq/programming.html#how-do-i-share-global-variables-across-modules –

14

Sie von Python globalen Variablen als „Modul“ Variablen denken kann - und als solche sind sie viel nützlicher als die traditionellen „globalen Variablen "von C.

Eine globale Variable ist tatsächlich in einem Modul __dict__ definiert und kann von außerhalb dieses Moduls als Modulattribut zugegriffen werden.

Also, in Ihrem Beispiel:

# ../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]) 

Und:

# ../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") 
2

Ihr zweiter Versuch perfekt funktioniert, und ist eigentlich eine wirklich gute Möglichkeit, Variablennamen zu handhaben, die Sie zur Verfügung haben wollen global. Aber Sie haben einen Namensfehler in der letzten Zeile. Hier ist, wie es sein sollte:

# ../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]) 

Siehe die letzte Zeile? myList ist ein Attr von globfile, nicht subfile. Dies wird funktionieren, wie Sie möchten.

Mike

6

Hai Vu Antwort funktioniert gut, nur einen Kommentar:

Falls Sie die globale in anderen Modul verwenden und Sie wollen dynamisch die global setzen, achten die anderen Module zu importieren, nachdem Sie die globalen Variablen gesetzt zum Beispiel:

# 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 
7

Siehe Pythons Dokument auf sharing global variables across modules:

The canonical way to share information across modules within a single program is to create a special module (often called config or cfg).

config.py:

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

Import the config module in all modules of your application; the module then becomes available as a global name.

main.py:

import config 
print config.x 

or

from config import x 
print x 

In general, don’t use from modulename import *. Doing so clutters the importer’s namespace, and makes it much harder for linters to detect undefined names.