Sichtbarkeit von globalen Variablen, die in importierten Modulen
Ich habe in ein bisschen ein Wand-Module zu importieren, die in einem Python-Skript. Ich werde mein bestes tun, um zu beschreiben, den Fehler, warum ich, und warum bin ich das binden dieser bestimmten Ansatz um mein problem zu lösen (was ich beschreiben werde, in einer Sekunde):
Nehmen wir an, ich habe ein Modul, in dem ich definiert habe einige utility-Funktionen/Klassen, die sich auf Entitäten definiert den namespace, in die das Hilfs-Modul importiert werden (lassen wir "eine" solche Person):
module1:
def f():
print a
Und dann habe ich das main-Programm, wo "a" ist definiert, in welche ich importieren möchten diese utilities:
import module1
a=3
module1.f()
Ausführung des Programms löst die folgende Fehlermeldung:
Traceback (most recent call last):
File "Z:\Python\main.py", line 10, in <module>
module1.f()
File "Z:\Python\module1.py", line 3, in f
print a
NameError: global name 'a' is not defined
Ähnliche Fragen gestellt zu haben in der Vergangenheit (vor zwei Tagen, d'uh) und mehrere Lösungen wurden vorgeschlagen, jedoch glaube ich nicht wirklich, dass diese passen meine Anforderungen. Hier mein Kontext:
Ich versuche zu machen, ein Python-Programm, das eine Verbindung zu einer MySQL-Datenbank-server und zeigt/ändert die Daten mit einem GUI. Der Sauberkeit halber habe ich definiert, das Bündel von Hilfs - /utility-MySQL-Funktionen in einer separaten Datei. Aber Sie alle haben eine gemeinsame variable, die ich hatte ursprünglich definiert innen dem utilities-Modul, und das ist der cursor Objekt aus MySQLdb-Modul.
Später habe ich realisiert, dass die cursor Objekt (die verwendet wird, um die Kommunikation mit dem db-server) definiert werden sollte, in der Haupt-Modul, , so dass sowohl die Haupt-Modul und alles, was importiert wird, in Sie kann auf dieses Objekt zugegriffen wird.
Ergebnis wäre so etwas wie dieses:
utilities_module.py:
def utility_1(args):
code which references a variable named "cur"
def utility_n(args):
etcetera
Und mein main-Modul:
program.py:
import MySQLdb, Tkinter
db=MySQLdb.connect(#blahblah) ; cur=db.cursor() #cur is defined!
from utilities_module import *
Und dann, sobald ich versuche zu rufen jedes der Programme Funktionen, löst die oben genannten "global name nicht definiert" - Fehler.
Einen bestimmten Vorschlag war, ein "aus dem Programm-import cur" - Anweisung in die utilities-Datei, wie diese:
utilities_module.py:
from program import cur
#rest of function definitions
program.py:
import Tkinter, MySQLdb
db=MySQLdb.connect(#blahblah) ; cur=db.cursor() #cur is defined!
from utilities_module import *
Aber, dass der zyklische import oder sowas und, unterm Strich, es stürzt auch. Also meine Frage ist:
Wie in der Hölle kann ich das "cur" - Objekt, definiert in der main-Modul, sichtbar für diejenigen, die Hilfs-Funktionen, die importiert es?
Vielen Dank für Ihre Zeit und meine tiefsten Entschuldigungen, wenn die Lösung schon gepostet hat an anderer Stelle. Ich kann einfach nicht die Antwort finden, die mich und ich habe keine mehr tricks in meinem Buch.
- Basierend auf Ihren update: Sie wollen wahrscheinlich nicht einen einzigen shared cursor sowieso. Eine einzige, gemeinsam genutzte Verbindung, ja, aber Cursor sind Billig, und es gibt oft gute Gründe zu haben, die mehrere Cursor lebendig zur gleichen Zeit (z.B., so dass Sie Durchlaufen können zwei von Ihnen im Gleichschritt anstatt
fetch_all
und Durchlaufen zwei Listen statt, oder einfach nur so können Sie zwei verschiedene threads/greenlets/callback-Ketten/was auch immer mit der Datenbank ohne Konflikte). - Sowieso, was Sie wollen zu teilen, ich denke, die Antwort ist hier zu bewegen
db
(undcur
, wenn Sie darauf bestehen) in ein separates Modul, dass sowohlprogram
undutilities_module
importieren aus. So dass Sie nicht bekommen, zirkuläre Abhängigkeiten (Import-Programm aus Modulen, die Programm-Importe) und die Verwirrung, die kommt mit.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Globals in Python sind weltweit zu einem Modul, nicht über alle Module. (Viele Menschen sind verwirrt, von diesem, weil, sagen wir, C, a global auf der gesamten Umsetzung aller Dateien, es sei denn, Sie wird explizit
static
.)Gibt es verschiedene Möglichkeiten, dieses Problem zu lösen, abhängig von Ihrer tatsächlichen Anwendungsfall.
Sogar vor, gehen auf diesem Weg, Frage dich, ob das wirklich sein muss global. Vielleicht haben Sie wirklich wollen, eine Klasse, mit
f
wie eine Instanz-Methode, sondern als nur eine Kostenlose Funktion? Dann könnte man etwas wie das hier tun:Wenn Sie wirklich wollen, eine Globale, aber es ist einfach da, verwendet zu werden, indem
module1
, setzen Sie ihn in das Modul.Auf der anderen Seite, wenn
a
ist geteilt durch eine ganze Menge von Modulen, legen Sie es irgendwo anders, und haben alle importieren:... , und in module1.py:
Nicht Verwendung eines
from
importieren, es sei denn, die variable ist vorgesehen, um eine Konstante.from shared_stuff import a
würde erstellen Sie eine neuea
variable initialisiert, wasshared_stuff.a
bezeichnet, die zum Zeitpunkt der Einfuhr, und diese neuea
Variablen nicht beeinflusst werden, durch Zuweisung anshared_stuff.a
.Oder in dem seltenen Fall, dass Sie wirklich brauchen, um wirklich global, überall, wie ein builtin ist, fügen Sie es zu der builtin-Modul. Die genauen details unterscheiden sich zwischen Python 2.x-und 3.x. In 3.x, es funktioniert wie folgt:
globals
ist der paradigmatische Fall der Hupen große Idee, die alles andere aufbaut auf (zumindest konzeptuell; in den details, die new-style-Klassen sind wohl das beste-Paradigma).Als workaround, könntest du überlegen, das setzen von environment-Variablen in der äußeren Schicht, wie in diesem.
main.py:
mymodule.py:
Als eine zusätzliche Vorsichtsmaßnahme, Griff dann der Fall, wenn MYVAL ist nicht definiert im Modul.
Einer Funktion Globale Variablen des Moduls ist es definiert in. Statt der Einstellung
a = 3
zum Beispiel, sollten Sie die Einstellungmodule1.a = 3
. Also, wenn Sie wollencur
erhältlich als global inutilities_module
legenutilities_module.cur
.Eine bessere Lösung: verwenden Sie nicht globals. Übergeben Sie die Variablen, die Sie brauchen, in den Funktionen, die Sie benötigen, oder erstellen Sie eine Klasse bündelt alle Daten zusammen und übergeben Sie es bei der Initialisierung der Instanz.
Dieser Beitrag ist nur eine Beobachtung für Python Verhalten, denen ich begegnete. Vielleicht sind die Ratschläge, die man liest oben nicht für Sie arbeiten, wenn Sie das gleiche, was ich weiter unten.
Nämlich, ich habe ein Modul, welches enthält den globalen/shared Variablen (wie oben vorgeschlagen):
Dann hatte ich das main-Modul importiert die gemeinsame Sachen mit:
und einige andere Module, die tatsächlich besiedelten diese arrays. Diese werden als durch das main-Modul. Beim beenden diese anderen Module kann ich deutlich sehen, dass die Felder ausgefüllt sind. Aber wenn Sie Lesen, die Sie zurück in das Haupt-Modul, Sie waren leer. Das war ziemlich befremdlich für mich (gut, ich bin neu in Python). Wenn ich jedoch die Art und Weise ändern, die ich importieren sharedstuff.py im Haupt-Modul:
es funktionierte (die arrays wurden aufgefüllt).
Just sayin'
Ist die einfachste Lösung für dieses spezielle problem wäre gewesen, hinzufügen andere Funktion innerhalb des Moduls gespeichert haben, den cursor in eine variable global für das Modul. Dann werden alle anderen Funktionen können Sie verwenden, wie gut.
module1:
main Programm:
Seit globals sind Modul-spezifisch, Sie können fügen Sie die folgende Funktion, um alle importierten Module, und dann verwenden, um:
.
Dann alles, was Sie brauchen, um passieren zu aktuellen globals:
Da ich es noch nicht gesehen haben in den Antworten oben, ich dachte, ich möchte hinzufügen, meine einfache Lösung, die ist nur um ein
global_dict
argument der Funktion, die der aufrufenden Moduls globals, und dann passieren die dict-in der Funktion beim Aufruf; e.g:Den OOP-Weg, dies zu tun wäre, um Ihr Modul eine Klasse anstelle einer Gruppe von ungebundenen Methoden. Dann könnten Sie
__init__
oder eine setter-Methode zum setzen der Variablen des Aufrufers für die Verwendung im Modul Methoden.