Konstanten mit einem Einstellungsmodul erstellen?

78

Ich bin relativ neu in Python. Ich möchte ein "Einstellungs" -Modul erstellen, in dem verschiedene anwendungsspezifische Konstanten gespeichert werden.

So möchte ich meinen Code einrichten:

settings.py

CONSTANT = 'value'

script.py

import settings

def func():
    var = CONSTANT
    # do some more coding
    return var

Ich erhalte eine Python-Fehlermeldung mit folgenden Angaben:

global name 'CONSTANT' is not defined.

Ich habe im Quellcode von Django festgestellt, dass ihre settings.pyDatei Konstanten hat, die genau wie ich benannt sind. Ich bin verwirrt darüber, wie sie in ein Skript importiert und über die Anwendung referenziert werden können.

BEARBEITEN

Vielen Dank für all Ihre Antworten! Ich habe folgendes versucht:

import settings

print settings.CONSTANT

Ich bekomme den gleichen Fehler

ImportError: cannot import name CONSTANT

Lerche
quelle
5
Das macht keinen Sinn. Sie sollten ein AttributeErrorif erhalten, settingsdas nicht definiert ist, CONSTANTund ein ImportErrorif, das keine Einstellungen importieren kann. In diesem Fall würde es nicht einmal CONSTANT
angezeigt
Gibt es etwas, was ich dann falsch mache?
Lerche
1
Fügen Sie die beiden Zeilen, die Sie zuletzt gepostet haben, genau so in eine Datei ein, wie Sie sie gepostet haben, und prüfen Sie, ob sie funktionieren.
Aaronasterling
1
Vielen Dank an alle für all Ihre Hilfe. Ich habe es herausgefunden. Dies hatte mit der Platzierung der init .py-Datei zu tun . Ich habe versucht, Einstellungen zu importieren, sodass Python sie nicht finden konnte. Nachdem ich auf die Verzeichniseinstellungen "Module" verwiesen hatte, funktionierte alles ordnungsgemäß. Im Grunde sieht meine import-Anweisung so aus: aus Modulen importieren Einstellungen. Ich denke, es gibt einen besseren Weg, dies zu tun, einen pythonischeren, also werde ich verschiedene Kombinationen ausprobieren. Nochmals vielen Dank für all Ihre Antworten.
Lerche

Antworten:

140

Der einfachste Weg, dies zu tun, besteht darin, Einstellungen nur als Modul zu verwenden.

(settings.py)

CONSTANT1 = "value1"
CONSTANT2 = "value2"

(consumer.py)

import settings

print settings.CONSTANT1
print settings.CONSTANT2

Wenn Sie ein Python-Modul importieren, müssen Sie den Variablen, die Sie daraus ziehen, den Modulnamen voranstellen. Wenn Sie genau wissen, welche Werte Sie in einer bestimmten Datei daraus verwenden möchten, und sich keine Sorgen darüber machen, dass sie sich während der Ausführung ändern, können Sie dies tun

from settings import CONSTANT1, CONSTANT2

print CONSTANT1
print CONSTANT2

aber ich würde mich nicht von dem letzten mitreißen lassen. Es macht es für Leute, die Ihren Code lesen, schwierig zu erkennen, woher Werte kommen. und schließt aus, dass diese Werte aktualisiert werden, wenn ein anderes Client-Modul sie ändert. Ein letzter Weg, dies zu tun, ist

import settings as s

print s.CONSTANT1
print s.CONSTANT2

Dies erspart Ihnen die Eingabe, verbreitet Aktualisierungen und erfordert nur, dass sich die Leser daran erinnern, dass alles, was danach skommt, aus dem Einstellungsmodul stammt.

aaronasterling
quelle
@delnan Ich habe es ausdrücklich vermieden, die Mechanik zu erwähnen, um Ihre Antwort nicht obsolet zu machen;)
aaronasterling
Nun, praktisch veraltet;) Die genaue Semantik zu kennen ist nützlich und vorzuziehen, aber damit es funktioniert, ist es nicht erforderlich - obwohl es notwendig ist, die Auswirkungen zu kennen, die in Ihrer Antwort ziemlich zusammengefasst sind.
3
Ich denke, die Idee der Konstanten ist, dass es zur Laufzeit nicht geändert werden kann?
Lie Ryan
@Lie Ryan, Python hat keine Konstanten. Bei Multiprogrammer-Projekten weiß man es nie.
Aaronasterling
1
@AaronMcSmoot: Ja, aber wenn Sie sogar die Absicht haben, eine Konstante nach der Laufzeit zu ändern, ist das sehr verdächtig, dass Sie das falsche Design haben.
Lie Ryan
17

Schritt 1: Erstellen Sie eine neue Datei settings.py im selben Verzeichnis, um den Zugriff zu erleichtern.

#database configuration settings

database = dict(
    DATABASE = "mysql",
    USER     = "Lark",
    PASS     = ""
)

#application predefined constants

app = dict(
    VERSION   = 1.0,
    GITHUB    = "{url}"
)

Schritt 2: Importieren des Einstellungsmoduls in Ihre Anwendungsdatei.

import settings as s            # s is aliasing settings & settings is the actual file you do not have to add .py 

print(s.database['DATABASE'])   # should output mysql

print(s.app['VERSION'])         # should output 1.0

Wenn Sie keinen Alias ​​wie s verwenden möchten, können Sie eine andere Syntax verwenden

from settings import database, app

print(database['DATABASE'])   # should output mysql

print(app['VERSION'])         # should output 1.0

Beachten Sie, dass Sie bei der zweiten Importmethode die Diktatnamen direkt verwenden können

Ein kleiner Tipp: Sie können den gesamten Code in die Einstellungsdatei mit * importieren, falls Sie eine große Datei haben und die meisten Einstellungen in Ihrer Anwendung verwenden

from settings import *      # * represent all the code on the file, it will work like step 2


print(database['USER'])       # should output lark

print(app['VERSION'])         # should output 1.0

Ich hoffe das hilft.

Fady Faried
quelle
5

Wenn Sie import settings, wird ein moduleaufgerufenes Objekt settingsin den globalen Namespace gestellt - und dieses Objekt trägt das settings.pyals Attribute. Dh außerhalb von settings.py, bezeichnen Sie CONSTANTals settings.CONSTANT.


quelle
4

Lassen Sie Ihre settings.py genau so wie sie ist, dann können Sie sie genauso verwenden wie Django:

import settings

def func():
    var = settings.CONSTANT
Ned Batchelder
quelle
3

... Oder wenn Sie wirklich möchten, dass alle Konstanten aus settings.py in den globalen Namespace importiert werden, können Sie ausführen

from settings import *

... aber ansonsten ist die Verwendung settings.CONSTANT, wie alle anderen hier erwähnt haben, ganz richtig.

ewall
quelle
In meiner Antwort finden Sie alle drei Möglichkeiten, die importAnweisung zu verwenden.
Aaronasterling
2
Eigentlich ist das nicht ratsam. Siehe z . B. docs.python.org/howto/doanddont.html#from-module-import . Obwohl es in diesem Fall den wahrscheinlich wünschenswerten Nebeneffekt hat, dass Änderungen an den Konstanten keine Auswirkungen auf andere Module haben.
2
Schön gesagt, @AaronMcSmooth. Und technisch gesehen habe ich nicht gesagt, dass es ratsam ist, * zu importieren, nur dass es möglich ist: P
ewall
@ Delnan. Ich bin mir nicht so sicher, ob das wünschenswert ist. Es hängt von der Anwendung ab, aber es könnte genauso wahrscheinlich sein, dass Änderungen weitergegeben werden (falls sie überhaupt auftreten)
aaronasterling
3

Siehe die Antwort, die ich an gepostet habe. Kann ich verhindern, dass ein Objekt in Python geändert wird? was macht, was Sie wollen (sowie die Verwendung von Großbuchstaben erzwingen). Es könnte tatsächlich eine bessere Antwort auf diese Frage sein als für die andere.

Martineau
quelle
2

Ich bin neu in Python, aber wenn wir eine Konstante wie eine Funktion in setings.py definieren

def CONST1():
    return "some value"

main.py.

import setings

print setings.CONST1() ##take an constant value

hier sehe ich nur einen, Wert kann nicht geändert werden, aber seine Arbeit wie eine Funktion ..

IVI
quelle
2

Dieser Weg ist effizienter, da Ihre Einstellungsvariablen nur einmal geladen / ausgewertet werden. Es funktioniert gut für alle meine Python-Projekte.

pip install python-settings

Dokumente hier: https://github.com/charlsagente/python-settings

Sie benötigen eine settings.py-Datei mit all Ihren definierten Konstanten wie:

# settings.py

DATABASE_HOST = '10.0.0.1'

Anschließend müssen Sie entweder eine env-Variable festlegen (SETTINGS_MODULE = settings exportieren) oder die configure-Methode manuell aufrufen:

# something_else.py

from python_settings import settings
from . import settings as my_local_settings

settings.configure(my_local_settings) # configure() receives a python module

Das Dienstprogramm unterstützt auch die Lazy-Initialisierung für schwer zu ladende Objekte. Wenn Sie also Ihr Python-Projekt ausführen, wird es schneller geladen, da die Einstellungsvariable nur bei Bedarf ausgewertet wird

# settings.py

from python_settings import LazySetting
from my_awesome_library import HeavyInitializationClass # Heavy to initialize object

LAZY_INITIALIZATION = LazySetting(HeavyInitializationClass, "127.0.0.1:4222") 
# LazySetting(Class, *args, **kwargs)

Konfigurieren Sie einfach einmal und rufen Sie jetzt Ihre Variablen auf, wo dies erforderlich ist:

# my_awesome_file.py

from python_settings import settings 

print(settings.DATABASE_HOST) # Will print '10.0.0.1'
charls
quelle
1

Versuche dies:

In settings.py:

CONSTANT = 5

In Ihrer Hauptdatei:

from settings import CONSTANT

class A:
    b = CONSTANT

    def printb(self):
         print self.b

Ich denke, Ihr obiger Fehler kommt von der Einstellungsdatei, die zu spät importiert wird. Stellen Sie sicher, dass es sich oben in der Datei befindet.

List
quelle
1

Ebenfalls einen Besuch wert ist das Projekt mit einfachen Einstellungen, mit dem Sie die Einstellungen bei Runtim in Ihr Skript einspeisen können, das umgebungsspezifische Einstellungen ermöglicht (denken Sie an dev, test, prod, ...).

Gregor
quelle