Forum: PC-Programmierung Python: globale Variablen?


von naj (Gast)


Lesenswert?

Hi
ich muss für die Uni ein Programm zur Auswahl von Kellern in ArcGis 
schreiben und habe da jetzt ewig lang Codes bzw ein ewig langes Skript. 
Da ich mich nicht so gut mit Python auskenne bräuchte ich jetzt Hilfe:

um das etwas handlicher zu machen, hab ich mir gedacht, das Programm als 
Modul in einem übersichtlicheren Skript aufzurufen. Da das aber nach dem 
Schema if,elif,else funktioniert, geht das mit import modulname nicht...
Jetzt habe ich gelesen, dass man globale Variablen definieren kann, aber 
entweder mach ich das falsch oder es geht aucht nicht.

Das sieht jetzt so aus:
def foo(a):
  global a
a = 2
import sys
sys.path.append('C:\Python27')
import modulname

Kann mir jemand weiterhelfen oder hat jemand andere Vorschläge wie man 
das "schön"  machen könnte?

von Silvan K. (silvan) Benutzerseite


Lesenswert?

Auszug aus der Dokumentation von Python 2.7.1:
1
4. Execution model
2
4.1. Naming and binding
3
[...]
4
If a name is bound in a block, it is a local variable of that block.
5
If a name is bound at the module level, it is a global variable.
6
(The variables of the module code block are local and global.)
7
If a variable is used in a code block but not defined there, it is a free variable.

von naj (Gast)


Lesenswert?

so hab ichs ja eigentlich auch gemacht...

Sowas wie

import sys
sys.path.append("C:\Python27")

import modulname "mit a = 2"

geht wohl nicht?

von Silvan K. (silvan) Benutzerseite


Lesenswert?

naj schrieb:
> so hab ichs ja eigentlich auch gemacht...

Dann versteh ich leider nicht, warum du das anders machen willst bzw. wo 
dein Problem mit dieser Methode ist :-(

von Silvan K. (silvan) Benutzerseite


Lesenswert?

ahhh...
Ich glaube, ich habs jetzt verstanden. Du willst in deinem Hauptscript 
die Variable mit einem Wert belegen, der dann im Modul verwendet wird?

von Yalu X. (yalu) (Moderator)


Lesenswert?

So ganz verstehe ich auch nicht, was du vorhast. Wie es scheint,
möchtest du die Variable a mit einem Wert an das Modul übergeben, so
dass sie dort als globale Variable gelesen werden kann. Das geht
so aber nicht, da importierte Module aus gutem Grund keine Variablen vom
importierenden Programm übernehmen.

Eine Möglichkeit wäre, das Modul nicht zu importieren, sondern mit
execfile() auszuführen. Dann wird der Code des Moduls in der gleichen
Ebene wie das importierende Programm ausgeführt und kann damit auch auf
die Variable a zugreifen. Aber sehr "schön" ist diese Methode nicht ;-)

Vielleicht hilft es unserem Verständnis auf die Sprünge, wenn du ein
einfaches Beispiel konstruierst, aus dem ersichtlich ist, was das Modul
tut und wie du es in dem übergeordneten Programm verwenden möchtest.

von naj (Gast)


Lesenswert?

sorry war den Abend über weg...

ich beschreib es jetzt noch mal genauer :)

a = ?
# das Fragezeichen durch die Nummer des gewünschten Komplexes ersetzen

if a == 0:
    arcpy.SelectLayerByAttribute_management ("ktreppe","NEW_SELECTION", 
" KKOMPLEXID = 0")
    arcpy.SelectLayerByAttribute_management ("kgang","NEW_SELECTION", " 
KKOMPLEXID = 0")
    arcpy.SelectLayerByAttribute_management ("kpfeiler","NEW_SELECTION", 
" KKOMPLEXID = 0")
    arcpy.SelectLayerByAttribute_management ("kraum","NEW_SELECTION", " 
KKOMPLEXID = 0")
    arcpy.SelectLayerByAttribute_management ("kschacht","NEW_SELECTION", 
" KKOMPLEXID = 0")

das Problem ist, dass es 341 verschiedene a's (Kellerkomplexe) gibt und 
das halt nicht sehr schön aussieht und auch in dem Programm extrem 
hängt. Deshalb war meine Idee, das der Endnutzer im Prinzip nur noch 
sieht:
a = ?
deshalb dachte ich, dass man das vlt mit import lösen könnte. Ich werde 
mir jetzt mal dieses execfile anschauen, ich hab halt gar keine 
Erfahrung mit Programmieren, deshalb kann ich mich da noch nicht so 
ausdrücken und versteh vieles nicht. Deshalb bin ich euch sehr dankbar 
für eure Hilfe!

von naj (Gast)


Lesenswert?

exec( "C:\Python27\dateiname.pyw",
          {'a': ?})

# das Fragezeichen durch die Nummer des gewünschten Komplexes ersetzen

so funktioniert es und sieht doch gar nicht schlecht aus! :)

von naj (Gast)


Lesenswert?

sorry, so stimmt es:

execfile( "C:\Python27\kellerfunktioniert.pyw",
         {'a': 2})

# das Fragezeichen durch die Nummer des gewünschten Komplexes ersetzen

von Yalu X. (yalu) (Moderator)


Lesenswert?

naj schrieb:
> if a == 0:
>     arcpy.SelectLayerByAttribute_management ("ktreppe","NEW_SELECTION",
> " KKOMPLEXID = 0")

D.h. die Anweisungen in dem Modul stehen frei und sind nicht in einer
Funktion oder eine Methode zusammengefasst?

Dann ist das auch kein "richtiges" Modul¹, und es ist in diesem Fall
durchaus in Ordnung, den Code mit execfile auszuführen, wie du es ja
erfolgreich gemacht hast.

Eine andere Möglichkeit wäre, das Ganze in eine Funktion mit einem
Argument zu packen, also etwa so:

kellermodul.py:
1
def kellerfunktion(a):
2
  if a == 0:
3
    ...
4
  elif a == 1:
5
    ...
6
  ...

main.py
1
from kellermodul import *
2
3
kellerfunktion(2)

———————————————
¹) Üblicherweise bestehen Module nur aus Klassen und Funktionen. Nur
   die Anweisungen für eine evtl. erforderliche Modulinitialisierung
   stehen frei, da sie beim Importieren des Moduls genau einmal aus-
   geführt werden sollen.

von Andreas M. (amesser)


Lesenswert?

Yalu X. schrieb:
> Eine andere Möglichkeit wäre, das Ganze in eine Funktion mit einem
> Argument zu packen, also etwa so:
>
> kellermodul.py:
>
1
> def kellerfunktion(a):
2
>   if a == 0:
3
>     ...
4
>   elif a == 1:
5
>     ...
6
>   ...
7
>
>
> main.py
>
1
> from kellermodul import *
2
> 
3
> kellerfunktion(2)
4
>

Das ist im Gegensatz zu dem 'import' Gefrickel mal ein vernünftiger 
Vorschlag.

@naj: Wenn Du etwas mehr Lust hast Dich mit Python zu beschäftigen, dann 
beschäftige Dich mal mehr mit Schleifen und vorallendingen, sehr sehr 
nützlich: Dictionaries. Damit kann man in Python sehr gut wartbaren 
kompakten und verständlichen Code schreiben. Gerade solche 
If-Abfrage-Ketten bei denen nur unterschiedliche Felder ausgewählt 
werden sollen sind so schon fast trivial. Beispiel:
1
kellerkomplexe = {
2
 0 : "ktreppe kgang kpfeiler kraum kschacht",
3
}
4
5
def kellerfunction(a):
6
  for x in kellerkomplexe[a].split():
7
    arcpy.SelectLayerByAttribute_management(x,"NEW_SELECTION","KKOMPLEXID = %u" % a)

Oder ist ktreppe, kgang bei jeder komplexid auszuwählen? Dann wirds 
trivial, aber das darfst Du selbst herausfinden.

von naj (Gast)


Lesenswert?

danke für die Tipps! Mein Problem war auch die ganze Zeit, dass ich 
nicht weiß wonach ich überhaupt suchen muss, aber jetzt kann ich ja gut 
drauf aufbauen :)

von naj (Gast)


Lesenswert?

wenn mir noch jemand sagen könnte für was das * nach import steht wäre 
ich wunschlos glücklich!

von troll (Gast)


Lesenswert?

naj schrieb:
> wenn mir noch jemand sagen könnte für was das * nach import steht wäre
> ich wunschlos glücklich!
[Glaskugel] * ist ein Platzhalter für "Alles". Also import * --> 
importiere alles

von Yalu X. (yalu) (Moderator)


Lesenswert?

Es gibt in Python mehrere Möglichkeiten, ein Modul oder Teile davon zu
importieren.


Variante 1:
1
import <Modul>

Bei der Verwendung von Von Klassen/Funktionen/Variablen aus dem Modul
muss immer der Modulname vorangestellt werden:
1
import kellermodul
2
3
kellermodul.kellerfunktion(2)


Variante 2:
1
from <Modul> import <Element 1>, <Element 2>, ...

Es werden nur die Klassen/Funktionen/Variablen <Element 1>, <Element 2>
usw. importiert. Sie werden ohne vorangestellten Modulnamen verwendet:
1
from kellermodul import kellerfunktion
2
3
kellerfunktion(2)

In dieser Variante können Elemente beim Importieren mit as umbenannt
werden, um Namenskonflikte zu vermeiden:
1
from kellermodul import kellerfunktion as untergeschossfunktion
2
3
untergeschossfunktion(2)


Variante 3:
1
from <Modul> import *

Es werden alle Klassen/Funktionen/Variablen importiert. Sie werden ohne
vorangestellten Modulnamen verwendet:
1
from kellermodul import kellerfunktion
2
3
kellerfunktion(2)

Diese letzte Variante ist die schreibfaulste. Bei Modulen mit vielen
Elementen besteht aber die Gefahr von Namenskonflikten, da dem Namens-
raum viele einzelne Namen hinzugefügt werden. Das in deinem Fall aber
wahrscheinlich kein Problem.

von naj (Gast)


Lesenswert?

Jetzt war ich heut in der Uni und wollte das ausprobieren und es kamen 
folgende Error meldungen:

Runtime error
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: No module named kellermodul

dabei befindet sich die Datei im selben Ordner.

dann hab ich mal nur eingegeben:

import arcpy
    arcpy.SelectLayerByAttribute_management ("ktreppe","NEW_SELECTION", 
" KKOMPLEXID = 0")
    arcpy.SelectLayerByAttribute_management ("kgang","NEW_SELECTION", " 
KKOMPLEXID = 0")
    arcpy.SelectLayerByAttribute_management ("kpfeiler","NEW_SELECTION", 
" KKOMPLEXID = 0")
    arcpy.SelectLayerByAttribute_management ("kraum","NEW_SELECTION", " 
KKOMPLEXID = 0")
    arcpy.SelectLayerByAttribute_management ("kschacht","NEW_SELECTION", 
" KKOMPLEXID = 0")

dann kam "Parsing error IndentationError: unexpected indent (line 2)"

jetzt hab ich das Zuhause noch mal probiert und hier kommen plötzlich 
die selben Fehlermeldungen...was ist denn jetzt schon wieder los?

von Yalu X. (yalu) (Moderator)


Lesenswert?

naj schrieb:
> Jetzt war ich heut in der Uni und wollte das ausprobieren und es kamen
> folgende Error meldungen:
>
> Runtime error
> Traceback (most recent call last):
>   File "<string>", line 1, in <module>
> ImportError: No module named kellermodul

Was hast du da genau gemacht? 'File "<string>"' sieht so aus, als
hättest du
1
  exec('import kellermodul')

o.ä. ausgeführt.

> dabei befindet sich die Datei im selben Ordner.

Schau mal, ob sys.path einen Leerstring ('') als Element enthält:
1
import sys
2
print sys.path

Dann sollte auch das Verzeichnis des aufrufenden Moduls nach Modulen
durchsucht werden.

> dann hab ich mal nur eingegeben:
>
> import arcpy
>     arcpy.SelectLayerByAttribute_management ("ktreppe","NEW_SELECTION",
> ...
>
> dann kam "Parsing error IndentationError: unexpected indent (line 2)"

Die zweite Zeile (arcpy...) darf nicht eingerückt sein. Python ist
einrückungssensitiv.

von naj (Gast)


Lesenswert?

jetzt funktioniert es wieder, ich hab jetzt beide dateien mal in den 
Pythonordner verschoben...komisch

Jetzt wollte ich mich mal mit Schleifen Dictionaries Sache auseinander 
setzen,
Die Zeile "kellerkomplexe = {0 : "ktreppe kgang kpfeiler kraum 
kschacht",}"
kann ich nachvollziehen.


"  for x in kellerkomplexe[a].split():
    arcpy.SelectLayerByAttribute_management(x,"NEW_SELECTION","KKOMPLEXID 
= %u" % a)"
heißt, dass x zB. ktreppe kgang kpfeiler kraum und kschacht entspricht 
und dann der selektionsbefehl in die 5 verschiedenen aufgeteilt wird 
oder?

aber was dann %u" % a bedeutet weiß ich nicht

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.