Ich bin auf eine Art Wand gestoßen, die Module in einem Python-Skript importiert. Ich werde mein Bestes tun, um den Fehler zu beschreiben, warum ich darauf stoße und warum ich diesen speziellen Ansatz zur Lösung meines Problems binde (den ich gleich beschreiben werde):
Angenommen, ich habe ein Modul, in dem ich einige Dienstprogrammfunktionen / -klassen definiert habe, die sich auf Entitäten beziehen, die im Namespace definiert sind, in den dieses Hilfsmodul importiert wird (sei "a" eine solche Entität):
Modul 1:
def f():
print a
Und dann habe ich das Hauptprogramm, in dem "a" definiert ist, in das ich diese Dienstprogramme importieren möchte:
import module1
a=3
module1.f()
Das Ausführen des Programms löst den folgenden Fehler aus:
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 wurden in der Vergangenheit gestellt (vor zwei Tagen, d'uh) und es wurden verschiedene Lösungen vorgeschlagen, aber ich denke nicht, dass diese meinen Anforderungen entsprechen. Hier ist mein besonderer Kontext:
Ich versuche ein Python-Programm zu erstellen, das eine Verbindung zu einem MySQL-Datenbankserver herstellt und Daten über eine GUI anzeigt / ändert. Aus Gründen der Sauberkeit habe ich die Reihe der MySQL-bezogenen Hilfs- / Dienstprogrammfunktionen in einer separaten Datei definiert. Jedoch haben sie alle eine gemeinsame Variable, die ich ursprünglich definiert war innerhalb des Versorgungsmoduls und die der Cursor - Objekt aus MySQLdb Modul. Später wurde mir klar, dass das Cursorobjekt (das zur Kommunikation mit dem Datenbankserver verwendet wird) im Hauptmodul definiert werden sollte, damit sowohl das Hauptmodul als auch alles, was in das Modul importiert wird, auf dieses Objekt zugreifen können.
Das Endergebnis wäre ungefähr so:
utilities_module.py:
def utility_1(args):
code which references a variable named "cur"
def utility_n(args):
etcetera
Und mein Hauptmodul:
program.py:
import MySQLdb, Tkinter
db=MySQLdb.connect(#blahblah) ; cur=db.cursor() #cur is defined!
from utilities_module import *
Sobald ich versuche, eine der Dienstprogrammfunktionen aufzurufen, wird der oben genannte Fehler "Globaler Name nicht definiert" ausgelöst.
Ein besonderer Vorschlag war, eine Anweisung "from program import cur" in die Dienstprogrammdatei aufzunehmen, wie folgt:
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 das ist zyklischer Import oder so ähnlich und unter dem Strich stürzt es auch ab. Meine Frage lautet also:
Wie zum Teufel kann ich das im Hauptmodul definierte "cur" -Objekt für die darin importierten Hilfsfunktionen sichtbar machen?
Vielen Dank für Ihre Zeit und meine tiefste Entschuldigung, wenn die Lösung an anderer Stelle veröffentlicht wurde. Ich kann die Antwort einfach nicht selbst finden und habe keine Tricks mehr in meinem Buch.
fetch_all
Gleichschritt durchlaufen, anstatt stattdessen zwei Listen durchlaufen zu müssen oder nur so können Sie zwei verschiedene Threads / Greenlets / Callback-Ketten / was auch immer verwenden, die die Datenbank ohne Konflikte verwenden).db
(undcur
, wenn Sie darauf bestehen), das beidesprogram
und esutilities_module
importiert. Auf diese Weise erhalten Sie keine zirkulären Abhängigkeiten (Importieren von Programmen aus Modulen, die vom Programm importiert werden) und die damit verbundene Verwirrung.Antworten:
Globale Werte in Python sind für ein Modul global und nicht für alle Module. (Viele Leute sind davon verwirrt, weil beispielsweise in C ein Global in allen Implementierungsdateien gleich ist, es sei denn, Sie machen es explizit
static
.)Abhängig von Ihrem tatsächlichen Anwendungsfall gibt es verschiedene Möglichkeiten, dies zu lösen.
Bevor Sie diesen Weg gehen, fragen Sie sich, ob dies wirklich global sein muss. Vielleicht möchten Sie wirklich eine Klasse
f
als Instanzmethode und nicht nur eine freie Funktion? Dann könnten Sie so etwas tun:Wenn Sie wirklich eine globale Version möchten, diese aber nur verwendet werden soll
module1
, legen Sie sie in diesem Modul fest.Wenn
a
es jedoch von vielen Modulen gemeinsam genutzt wird, platzieren Sie es an einem anderen Ort und lassen Sie es von allen importieren:… Und in module1.py:
Sie nicht eine Verwendung
from
Import es sei denn , die Variable soll eine Konstante sein.from shared_stuff import a
würde eine neuea
Variable erstellenshared_stuff.a
, die auf das initialisiert ist, worauf zum Zeitpunkt des Imports Bezug genommen wurde, und diese neuea
Variable wäre von Zuweisungen an nicht betroffenshared_stuff.a
.Oder, in dem seltenen Fall, dass Sie es wirklich brauchen, um überall wirklich global zu sein, wie ein eingebautes, fügen Sie es dem eingebauten Modul hinzu. Die genauen Details unterscheiden sich zwischen Python 2.x und 3.x. In 3.x funktioniert es folgendermaßen:
quelle
Um dieses Problem zu umgehen, können Sie Umgebungsvariablen wie folgt in der äußeren Ebene festlegen.
main.py:
mymodule.py:
Behandeln Sie als zusätzliche Vorsichtsmaßnahme den Fall, wenn MYVAL nicht im Modul definiert ist.
quelle
Eine Funktion verwendet die Globals des Moduls, in dem sie definiert ist . Anstatt
a = 3
beispielsweise Einstellungen vorzunehmen , sollten Sie Einstellungen vornehmenmodule1.a = 3
. Wenn Sie alsocur
als globales In verfügbar sein möchtenutilities_module
, legen Sie festutilities_module.cur
.Eine bessere Lösung: Verwenden Sie keine Globals. Übergeben Sie die benötigten Variablen an die Funktionen, die sie benötigen, oder erstellen Sie eine Klasse, um alle Daten zu bündeln, und übergeben Sie sie beim Initialisieren der Instanz.
quelle
Dieser Beitrag ist nur eine Beobachtung des Python-Verhaltens, auf das ich gestoßen bin. Vielleicht funktionieren die Ratschläge, die Sie oben gelesen haben, nicht für Sie, wenn Sie dasselbe gemacht haben, was ich unten getan habe.
Ich habe nämlich ein Modul, das globale / gemeinsam genutzte Variablen enthält (wie oben vorgeschlagen):
Dann hatte ich das Hauptmodul, das die gemeinsam genutzten Inhalte importiert mit:
und einige andere Module, die diese Arrays tatsächlich gefüllt haben. Diese werden vom Hauptmodul aufgerufen. Beim Beenden dieser anderen Module kann ich deutlich sehen, dass die Arrays gefüllt sind. Beim Zurücklesen im Hauptmodul waren sie jedoch leer. Das war ziemlich seltsam für mich (nun, ich bin neu in Python). Wenn ich jedoch die Art und Weise ändere, in der ich die Datei sharedstuff.py im Hauptmodul importiere, in:
es funktionierte (die Arrays wurden gefüllt).
Ich sag bloß'
quelle
Die einfachste Lösung für dieses spezielle Problem wäre gewesen, eine weitere Funktion innerhalb des Moduls hinzuzufügen, die den Cursor in einer globalen Variablen zum Modul gespeichert hätte. Dann könnten es auch alle anderen Funktionen nutzen.
Modul 1:
Hauptprogramm:
quelle
Da Globals modulspezifisch sind, können Sie allen importierten Modulen die folgende Funktion hinzufügen und sie dann verwenden, um:
Dann brauchen Sie nur noch die aktuellen globalen Informationen weiterzugeben:
quelle
Da ich es in den obigen Antworten nicht gesehen habe, dachte ich, ich würde meine einfache
global_dict
Problemumgehung hinzufügen, indem ich der Funktion, die die Globals des aufrufenden Moduls erfordert, nur ein Argument hinzufüge und dann das Diktat beim Aufruf an die Funktion übergebe. z.B:quelle
Die OOP-Methode hierfür besteht darin, Ihr Modul zu einer Klasse anstelle einer Reihe ungebundener Methoden zu machen. Dann können Sie
__init__
oder eine Setter-Methode verwenden, um die Variablen des Aufrufers für die Verwendung in den Modulmethoden festzulegen.quelle