Seite 1 von 2

Grundlage "import"

Verfasst: Montag 12. Januar 2015, 02:38
von MoonKid
Bin sehr frisch mit Python.

Code: Alles auswählen

#!/usr/bin/python3
# -*- coding: utf-8 -*-
from sqlalchemy import *
#import sqlalchemy
print(__version__)
Der sinnhafte Unterschied zwischen den beiden Import-Varianten ist mir klar.
Bei der hier auskommentierten Variante könnte ich einfach sqlalchemy.__version__ schreiben. Wie ist es bei der anderen Variante? __version__ scheint sich hier (vermutlich aus Sicherheitsgründen) jedoch nicht im globalen Namensraum zu befinden.
Wie könnte ich sowas lösen, ohne auf das einfache import zurückzugreifen?

Re: Grundlage "import"

Verfasst: Montag 12. Januar 2015, 08:17
von mutetella
MoonKid hat geschrieben:__version__ scheint sich hier (vermutlich aus Sicherheitsgründen) jedoch nicht im globalen Namensraum zu befinden.
Doch, genau im globalen Namensraum befindet sich ``__version__``. Und mit Sicherheit hat das nichts mit Sicherheit zu tun, auch wenn manchmal behauptet wird, dass doppelte Unterstriche den Zugriff auf einen Namen von außen verhindern und damit sicher machen würden. Das ist Quatsch.

Sternchenimporte importieren in den Namensraum des importierenden Moduls. Deshalb kannst Du ja eben ``print(__version__)`` machen.
Wenn nun allerdings das importierende Modul selbst einen Namen ``__version__`` besitzt oder Du nach dem Sternchenimport nochmals einen Sternchenimport eines Moduls machst, das ebenfalls den Namen ``__version__`` verwendet, wird ``__version__`` jedesmal überschrieben. Und genau deswegen solltest Du Sternchenimporte auch vermeiden. Ein weiterer Grund das zu vermeiden ist auch der, dass ein ``sqlalchemy.__version__`` ganz klar ausdrückt, worauf sich ``__version__`` bezieht. Dein Code wird dadurch leichter lesbar und verständlicher.

Wenn man, aus welchen Gründen auch immer, nur Teile eines Moduls importieren möchte, kann man auch ``from sqlalchemy import __version__ as sqlversion`` machen. Damit importierst Du nur die Konstante ``__version__`` in den Namensraum des importierenden Moduls und bindest diese dort an den Namen ``sqlversion``. Oder ``from sqlalchemy import __version__`` ohne einen eigenen Namen für ``__version__`` zu vergeben.

Ich persönlich bevorzuge das Importieren des gesamten Moduls und den Zugriff auf dessen Inhalt über den Punktoperator. Damit weiß ich immer, woher die Dinge stammen...

mutetella

Re: Grundlage "import"

Verfasst: Montag 12. Januar 2015, 08:53
von Sirius3
@mutetella: Außnahmsweise hat das mal doch was mit Sicherheit zu tun, dass nämlich nicht jeder blöde *-Import wichtige Systemvariablen überschreibt. Bei einem *-Import werden nur die Namen importiert, die nicht mit einem _ anfangen (solange nicht ein __all__ etwas anderes vorschreibt).

@MoonKid: trotzdem sollte man keine *-Importe machen, sondern die Namen, die man braucht explizit in den eigenen Namensraum holen, oder über den .-Operator darauf zuzugreifen.

Re: Grundlage "import"

Verfasst: Montag 12. Januar 2015, 10:26
von mutetella
@Sirius3
Wenn ich mir mal sicher bin... :oops: Again what learned!

mutetella

Re: Grundlage "import"

Verfasst: Montag 12. Januar 2015, 21:50
von MoonKid
Vielen Dank für die Tips.

Könnt ihr bei der Gelgenheit eine Art Liste empfehlen mit Regeln für elegantes und sinnvolles Pythonschreiben, oder eine entsprechende NO-GO-Liste.

Von C++ kenne ich sowas, da kann man aber auch n bisl mehr Unsinn anstellen.

Re: Grundlage "import"

Verfasst: Montag 12. Januar 2015, 22:06
von darktrym
Apropos No-Gos, dein Shebang geht auch dazu.

Re: Grundlage "import"

Verfasst: Montag 12. Januar 2015, 22:15
von cofi
@darktrym: Dann sollte man vielleicht noch erwaehnen, was das entsprechende "Go" waere.

In dem Fall also

Code: Alles auswählen

#!/usr/bin/env python3

Re: Grundlage "import"

Verfasst: Montag 12. Januar 2015, 22:21
von BlackJack
Style Guide for Python Code und Python is not Java wären vielleicht erwähnenswert. Und ``import this`` mal ausführen. :-)

Re: Grundlage "import"

Verfasst: Montag 12. Januar 2015, 22:23
von darktrym
Wobei ich mich frage, warum man den Code auf Python 3 beschränken sollte. Eine 4. wirds wohl nicht geben und 2 ist wohl nicht gewollt? Das Shebang hat die Aufgabe der Shell deutlich zu machen, das nun kein Shellscript folgt und er doch bitte an jenen Interpreter abgeben soll und nicht für die Kompat. einzelner Programmiersprachen zu sorgen. Ich lass die Zahl immer weg.

Re: Grundlage "import"

Verfasst: Montag 12. Januar 2015, 22:29
von BlackJack
@darktrym: Man sollte IMHO schon die passende Version dort angeben, also bei Python 3 wäre das ``python3``. Mir ist jedenfalls noch kein System bekannt das als ``python`` *nicht* Python 2.irgendwas verwendet. Wenn man also Python 3 Quelltext schreibt ist nur ``python`` mit an Sicherheit grenzender Wahrscheinlichkeit der falsche Interpreter.

Re: Grundlage "import"

Verfasst: Montag 12. Januar 2015, 22:57
von darktrym
Mit sicher gehender Wahrscheinlichkeit wird das Programm in Zukunft den Dienst versagen wenn nicht stets der symbolische Link von python auf python3 existiert. Ist hier auch schon so, dass ich von 2.7 auf "" linken muss und den gleichen Spaß bei 3.4 auf 3 hab. Im Sinne der Wartbarkeit ist das nicht optimal und innerhalb der Major Version ändern sich schon genug Sachen gerade bzgl. Abwärtskomp.

Re: Grundlage "import"

Verfasst: Montag 12. Januar 2015, 23:52
von BlackJack
@darktrym: Irgendwie verstehe ich Deinen Beitrag nicht. ``python`` ist *immer* ``python2`` und ich glaube auch nicht das sich daran innerhalb der nächsten 5 Jahre bis zum offiziellen Ende von Python 2.7 etwas ändern wird und wohl auch mindestens 5 Jahre danach nicht. Wer einen Link von ``python`` auf eine installierte ``python3.x`` legt schiesst sich selbst in den Fuss. Für Windows gibt es ausserdem ja diesen Starter der die Shebang-Zeile anschaut und bei ``python`` ein installiertes Python 2 und bei ``python3`` ein installiertes Python 3 benutzt um die Datei mit der Endung ``.py`` dann tatsächlich auszuführen. Auch der würde nicht mehr richtig funktionieren wenn man bei Python 3 Quelltext nur ``python`` in die Shebang-Zeile schreibt.

Re: Grundlage "import"

Verfasst: Dienstag 13. Januar 2015, 03:00
von DasIch
PEP 394 ist legt übrigens fest was genau `python` machen sollte und zwar Python 2 ausführen. Außerdem legt es fest das Skripte *immer* explizit python2 oder python3 benutzen sollten. `/usr/bin/env python` ist also auch nicht akzeptabel.

Re: Grundlage "import"

Verfasst: Dienstag 13. Januar 2015, 03:28
von MoonKid
mutetella hat geschrieben:bevorzuge das Importieren des gesamten Moduls und den Zugriff auf dessen Inhalt über den Punktoperator
Verstehe. Das kann ich gut nachvollziehen.

Wie würdest du das hier lösen?

Code: Alles auswählen

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import *

Re: Grundlage "import"

Verfasst: Dienstag 13. Januar 2015, 07:13
von MoonKid
Uhrzeitbedingt hab ich mich wahrscheinlich unspezifisch ausgedrückt.

Wie gehe ich mit Modulen um, die einen Punkt im Namen haben?
Oder anders: Was genau ist das?

Sind es tatsächlich simple Module mit Punkt im Namen? Oder gibt es tatsächlich, die durch den Punkt suggerierte Hirarchie in den Modulen?

Re: Grundlage "import"

Verfasst: Dienstag 13. Januar 2015, 08:42
von Sirius3
@MoonKid: Der Punkt ist eine Hierarchie. Und gerade weil sqlalchemy so viele Objekte hat, sollte man sie explizit importieren.
Zum Beispiel:

Code: Alles auswählen

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.types import Integer, Numeric, String, DateTime, Boolean
from sqlalchemy.schema import Column, MetaData, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship
Ist jetzt nicht so viel Arbeit und hilft einem wirklich zu wissen, was gebraucht wird.

Re: Grundlage "import"

Verfasst: Dienstag 13. Januar 2015, 18:54
von DasIch
MoonKid hat geschrieben:Verstehe. Das kann ich gut nachvollziehen.

Wie würdest du das hier lösen?

Code: Alles auswählen

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import *
Zwar nicht mutella, aber... sowas macht man grundsätzlich nicht. `from ... import *` ist eine nette Hilfe wenn man sich in einer Python Shell befindet, ansonsten ist es unakzeptabel es einzusetzen, es sei das Modul in dem man so importiert sowie das Modul aus dem man importiert sind teil desselben Projekts. Selbst in diesem einen Ausnahmefall in dem es prinzipiell akzeptabel ist, sollte man es nicht ohne Grund tun.

Re: Grundlage "import"

Verfasst: Mittwoch 14. Januar 2015, 13:10
von MoonKid
Sirius3 hat geschrieben:

Code: Alles auswählen

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, relationship
Ist jetzt nicht so viel Arbeit und hilft einem wirklich zu wissen, was gebraucht wird.
Verstehe. Das widerspricht aber dem Vorschlag, alle Modulelemente grundsätzlich mit Ihrem Modulnamen anzusprechen. Also z.B.

Code: Alles auswählen

sqlalchemy.create_engine
Was mache ich mit Untermodulen?

Code: Alles auswählen

import sqlalchemy as sqla
db = sqla.create_engine("...")
ses = sqla.orm.sessionmaker(...)
sqla.ext.declarative.declarative_base...
Sieht irgendwie komisch aus.

Re: Grundlage "import"

Verfasst: Mittwoch 14. Januar 2015, 13:22
von BlackJack
@MoonKid: Ja Du hast da jetzt zwei Widersprüchliche Vorschläge bekommen. Weil verschiedene Leute das unterschiedlich handhaben. Sowas aber auch. :-)

Re: Grundlage "import"

Verfasst: Mittwoch 14. Januar 2015, 14:54
von MoonKid
BlackJack hat geschrieben:@MoonKid: Ja Du hast da jetzt zwei Widersprüchliche Vorschläge bekommen. Weil verschiedene Leute das unterschiedlich handhaben. Sowas aber auch. :-)
:oops: :P Sorry, wollte jetzt niemandem einen "Fehler" vorhalten. :mrgreen:
Mir is natürlich klar, dass es mehr Wege gibt, obwohl Pythons Philosophie sowas ja verhindern möchte.

War eher daran interessiert, welche diversen(!) Lösungsmöglichkeiten erfahrende Python-er so nutzen.