Home » Beitrag verschlagwortet mit 'Python'

Schlagwort-Archive: Python

Flask Application Programming Setup (mit PostgresSQL)

Was muss gemacht werden, um eine Flask Beispiel-Applikation im eingenen Workspace zum Laufen zu kriegen?

PostgesSQL DB: Sind die Entitäten vorhanden

Starten der DB: pg_ctl -D „C:\Program Files\PostgreSQL\13\data“ start

In die DB einloggen: psql <db_namen> <user_namen>, z.B. psql todoDB postgres
Dann innerhalb PSQL Shell:
\l : Um DBs zu listen
\dt: Um Tabellen zu listen
\? : Um andere Kommanos kennen zu lernen

Die Flask App zum Laufen kriegen

Im Windows Dos Prompt:

set FLASK_APP=<relativer_pfad_zum_app.py_file>

set FLASK_DEBUG=true damit der server dann automatisch die Codeänderungen rein lädt (life Editing)

flask run

Libraries würde man mit dem PIP (Package Manager laden).

In Flask: JavaScript als File auslagern

Symptom: Dieser seltsame Fehler:

sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) FEHLER: ungültige Eingabesyntax für Typ integer: »app.js«
LINE 3: WHERE todolists.id = ‚app.js‘

Lösung: Korrektes Referenzieren des Javascript-Files in einer Flask-Applikation:

In Flask apps stehen JavaScript und CSS files standardmässig in einem static genannten directory neben dem templates Directory, das die HTML templates enthält.

Im HTML-File wird ein File (z.B. Namens app.js) dann so referenziert:

<script src="{{url_for('static', filename='app.js')}}"></script>

Achtung: Das Scripts-Tag muss am Ende des Bodies stehen.

SQLAlchemy/Python DB-Manipulation basierend of ORM Model

Wenn z.B. ein Python File vorliegt, dass DB-Connectivity und Entitätenmodell definiert:
(Python interpreter wurde aus dem Verzeichnis mit dem app.py gestartet. FLASK_APP Environmentvariable zeigte auch auf das app.py File.)

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:admin@localhost:5432/todoDB'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

class TodoList(db.Model):
  __tablename__ = 'todolists'
  id = db.Column(db.Integer, primary_key=True)
  name = db.Column(db.String(), nullable=False)
  todos = db.relationship('Todo', backref='list', lazy=True)

  def __repr__(self):
    return f'<TodoList {self.id} {self.name}>'

class Todo(db.Model):
  __tablename__ = 'todos'
  id = db.Column(db.Integer, primary_key=True)
  description = db.Column(db.String(), nullable=False)
  completed = db.Column(db.Boolean, nullable=False, default=False)
  list_id = db.Column(db.Integer, db.ForeignKey('todolists.id'), nullable=False)

  def __repr__(self):
    return f'<Todo {self.id} {self.description}, list {self.list_id}>'

Beachte: Der Foreign Key heisst ‚list_id‚, die ‚backref‘ wird aber mit ‚list‚ angegeben und auch das TodoList-Parent-Objekt wird (siehe unten) an die Referenz Todo.list angehängt.

Dann können mittels Python auf der Commandline folgendermassen Entitäten erstellt und gespeichert werden:

C:\tmp\Python_Workspace1\step4-todoapp-crud-lists>python
Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 16:30:00) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from app import db, Todo, TodoList
>>> list1 = TodoList(name='Haushalt')
>>> todo1 = Todo(description='putzen')
>>> todo2 = Todo(description='kochen')
>>> todo1.list=list1
>>> todo2.list=list1
>>> list1.id=3
>>> db.session.add(list1)
>>> db.session.commit()

Resultat:

todoDB=# select * from todos;
 id | description | completed | list_id
----+-------------+-----------+---------
  6 | putzen      | f         |       3
  7 | kochen      | f         |       3
(5 Zeilen)


todoDB=# select * from todolists;
 id |     name
----+---------------
  3 | Haushalt
(3 Zeilen)


todoDB=#

Flask DB Migrations

Links

Flask-Migrate ist die Library um DB-Modell-Änderungen, die mit SQLAlchemy ausgedrückt sind zu kontrollieren. Es benutzt dazu die Library Alembic.

Schritte

Aufsetzen Flask Migrate Tool

Steps:

pip3 install Flask-Migrate

Projekt bezüglich Migrations-Handling aufsetzen

flask db init

Das setzt verschiedene Migrations-Script-Folders und Tools im SW-Projekt bereit.


Output:

C:\tmp\Python_Workspace1\task-app>flask db init
Creating directory C:\tmp\Python_Workspace1\task-app\migrations ...  done
Creating directory C:\tmp\Python_Workspace1\task-app\migrations\versions ...  done
Generating C:\tmp\Python_Workspace1\task-app\migrations\alembic.ini ...  done
Generating C:\tmp\Python_Workspace1\task-app\migrations\env.py ...  done
Generating C:\tmp\Python_Workspace1\task-app\migrations\README ...  done
Generating C:\tmp\Python_Workspace1\task-app\migrations\script.py.mako ...  done
Please edit configuration/connection/logging settings in 'C:\\tmp\\Python_Workspace1\\task-app\\migrations\\alembic.ini' before proceeding.

Funktioniert das Kommando nicht, weil die DB noch nicht gestartet ist, dann etwa folgendes absetzen:

pg_ctl -D "C:\Program Files\PostgreSQL\13\data" start

DB-Migrationen durchführen

flask db migrate

Erkennt die Anforderungen an das DB-Modell aus den Python-Scripts (aus den SQLAlchemy Model-Objekt-Definitionen) heraus und erstellt eine Migration (DDL Statements um das erforderliche DB-Model zu erstellen).
Ich gehe schwer davon aus, das dazu FLASK_APP auf das Python-Script mit den Entitätsdefinitionen zeigen muss.

Bsp. einer SQLAlchemy Model-Objekt-Definition im *.py:

class Todo(db.Model):
    __tablename__ = 'todos'
    id = db.Column(db.Integer, primary_key=True)
    description = db.Column(db.String(), nullable=False)

Falls das erzeugte Script das ganze DB-Modell von Grund auf neu erzeugen soll, dann darf die DB diese Entitäten nicht schon enthalten. Das kann man zum Bsp. erreichen durch:

dropdb --username=postgres todoDB
createdb --username=postgres todoDB

!Stelle sicher, dass das Pyton-Script, nicht schon selbst die DB-Objekte erstellt (Z.B. Kommando db.create_all() darf nicht auch schon im Python-Code enthalten sein).

Durchführung:

C:\tmp\Python_Workspace1\task-app>flask db migrate

INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'todos'
Generating C:\tmp\Python_Workspace1\task-app\migrations\versions\70ee48c313e4_.py ...  done

C:\tmp\Python_Workspace1\task-app>

Ein Migrations-File wurde erstellt: task-app/migrations/versions/70ee48c313e4_.py:

"""empty message

Revision ID: 70ee48c313e4
Revises: 
Create Date: 2021-07-22 15:15:43.733091

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '70ee48c313e4'
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('todos',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('description', sa.String(), nullable=False),
    sa.PrimaryKeyConstraint('id')
    )
    # ### end Alembic commands ###


def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('todos')
    # ### end Alembic commands ###

Migration auf die DB spielen:

C:\tmp\Python_Workspace1\task-app>flask db upgrade
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> 70ee48c313e4, empty message

Migration rückgängig machen wäre:

flask db downgrade

Prüfung, ob DB-Migrationen auf DB angekommen sind:

C:\tmp\Python_Workspace1\task-app>psql --username=postgres todoDB
Passwort für Benutzer postgres:
todoDB=# \dt
              Liste der Relationen
 Schema |      Name       |   Typ   | Eigent³mer
--------+-----------------+---------+------------
 public | alembic_version | Tabelle | postgres
 public | todos           | Tabelle | postgres
(2 Zeilen)


todoDB=#

Beachte die alembic_version Tabelle! Beinhaltet die Migrationsinfo. Prinzipiell nicht durch den Programmierer zu verändern.

Wenn nun Änderungen am DB-Modell innerhalb des Python-Scripts gemacht werden (z.B. wird hier das boolean Feld ‚completed‘ neu hinzu gefügt),

class Todo(db.Model):
    __tablename__ = 'todos'
    id = db.Column(db.Integer, primary_key=True)
    description = db.Column(db.String(), nullable=False)
    completed = db.Column(db.Boolean(), nullable=False, default=False)

…, dann wird mit flask db migrate ein neues Update-Script erstellt und mit flask db update dieser Update auf die DB gespielt.

Beheben der Problematik des Hinzufügens von NOT-NULL Feldern:
Das Migrations-Script folgendermassen anpassen:

from alembic import op

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('todos', sa.Column('completed', sa.Boolean(), nullable=True))
    op.execute('update todos set completed=False where completed is null')
    op.alter_column('todos', 'completed', nullable=False)
    # ### end Alembic commands ###

Flask WebApp Request handling

Request-Typen und ihr Handling

Request-TypHandling (Python)
URL parameter:
/foo?field1=value
value1 = request.args.get(field1)
Form inputun = reqest.form.get(‚username‘)
pw = request.form.get(‚password‘)
application/jsondata_string = request.data
data_dictionary = json.loads(data_string)

DB Manipulation with SQLAlchemy

Referenzen:
Docs for the SQLAlchemy Query API
SQLAlchemy Doku

Im folgenden eine Kleine Demo,
– wie bestehende SQLAlchemy-Definitionen eines bestehendes Python-Scripts in die interaktive Python-Konsole importier werden können und
– wie SQLAlchemy-Entitäten SQLAlchemy-artig von der abgefragt und hinzu gefügt werden.

AblaufCommandMeaning
1>pythonStart Python Console
2>from path/flask_postgres_sql_hello_app import db,PersonImportiert die in flask_postgres_sql_hello_app.py
(–> siehe) gemachten Definitionen von db und Person
3ffresults = Person.query.all()Holt alle Person Entitäten von der entsprechenden Tabelle
3ffresults = Person.query.first()
3ffPerson.query.filter_by(name=’Hans‘).all()

#Alternativ:
Person.query.filter(Person.name=’Hans‘).all()

#Alternativ:
db.session.query(Person).filter(Person.name=’Hans‘).all()
Holt Person Entitäten die dem Filter entsprechen von der entsprechenden Tabelle
User.query.filter(User.name.like(‚B%‘)).all()

ilike(‚b%‘)
Like-Query

Like (Case-insensitive)
3ffPerson.query.filter(Person.name==‚Hans‘).filter(Person.name==‚Peter‘).all()Multiple Filters (Method chaining)
3ffquery.count()
query.first()
query.get(9)
query.get(‚ID1‘)
query.limit(2)
query.delete()

query.order_by(db.desc(Person.name))
Wird für Grouping benutzt
Nur erstes Finding bringen
Nur 9tes Finding bringen
Primary-Key filter
Nur die ersten 2
Löschen des Query-Resultats

Order by
Person.query.join(‚vehicles‘).filter(Vehicle.marke==‚Opel‘).all()Join-Beispiel
3ffperson = Person(name=’Bob‘)
db.session.add(person)
db.sesssion.commit()
Erstellen eines Person-Objekts und speichern desselben.
3ffdb.session.add_all([Person(name=’Ada‘), Person(‚Jira‘)])
db.sesssion.commit()
Erstellen mehrerer Person-Objekt und speichern desselben
3ff
3ff
3ff

Erste Flask Python Webapp mit DB zugriff über sqlAlchemy

Referenzen

Overall Example

Python HTTP-Server (Flask) Applikation, die vom Browser aufgerufen mit ‚Hello <name>‘ antwortet, wobei der Name von der Personen-Tabelle der DB gelesen wird.
Flask wird dabei benutzt um den HTTP Server zur Verfügung zu stellen und darin die Web-App auf definierter URL anzubieten.
SQLAlchemy (in der Flask-Version) bietet die APIs um DB Entitäten als Klassen (z.B. ‚Person‘) formulieren zu können diese als Objekte auf die relationale DB zu mappen (ORM provider).

flask-postgres-sql-hello-app.py:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__) #Create a flask app with the name of this runnable python file (stored in the env var __name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://myDB:pw@localhost:5432/testDB'
db = SQLAlchemy(app)

class Person(db.Model):
  __tablename__ = 'persons'
  id = db.Column(db.Integer, primary_key=True)
  name = db.Column(db.String(), nullable=False)

#create all defined entities:
db.create_all()

#Insert an object to the DB:
person1 = Person(name = 'Marc')
db.session.add(person1)
db.session.commit()

person = Person.query.first()

#Handle web request on the web root:
@app.route('/')
def index():
    return 'Hello ' + person.name

# Wird dieser Code auskommentiert, dann kann diese HTTP-Server-App 
# durch 'python dieses-file-py' gestartet werden.
#if __name__ == '__main__':
#   app.run()

Define an Entity

class Person(db.Model):
  __tablename__ = 'persons'
  id = db.Column(db.Integer, primary_key=True)
  name = db.Column(db.String(), unique=False, nullable=False)
  ahv = db.Column(db.String(), unique=True, nullable=False)

How to run a Flask HTTP Server

Das obige HTTP-Server-Script flask-postgres-sql-hello-app.py wird gestartet mit:

> flask run

nachdem die Umgebungsvariablen FLASK_APP=pfad/flask-postgres-sql-hello-app.py gesetzt ist (Windows).
In Linux wird anscheinend so aufgerufen: >FLASK_APP=pfad/flask-postgres-sql-hello-app.py flask run

Debug-Mode: (Autorerun des HTTP-Server-Scripts)
Env. Variable setzen: FLASK_DEBUG=true

Remark flask --reload probably does the same as set FLASK_DEBUG=TRUE: Reloads the app as soon as code has changed.

Alternative Start-Methode:
Sieh code auch oben:

# Wird dieser Code auskommentiert, dann kann diese HTTP-Server-App 
# durch 'python dieses-file-py' gestartet werden.
#if __name__ == '__main__':
#   app.run()

Soll die Server-App von aussen Aufrufbar sein:

>flask run --host=0.0.0.0

oder

if __name__ == '__main__':
   app.run(host="0.0.0.0")

Use Python Interactive Console to Import script and query script defined Entities

C:\tmp\Python_Workspace1\src>python

>>> from flask_postgres_sql_hello_app import db,Person
>>> Person.query.all()
[<Person ID: 5, name: Marc>
, <Person ID: 9, name: Marc>
, <Person ID: 10, name: Marc>

Funktioniert nur mit PY-Files deren Namen nach Konvention ist (kein ‚-‚).

Object Lifecycle in SQLAlchemy

The Lifecycle is: –object instantiated–> transient— query add executed–> pending –qery select/filter OR commit exec–> flushed –commit ex.–> committed

Flushed heisst: Im internen (in Memory) ORM-Object-Model-Cache sind die Änderungen bereits geschrieben.

!! ORM Selects (z.B. Person.query.all()) erhält bereits alle Objekte, die oberhalb im Code mit session.query.add(person) hinzugefügt/verändert/gelöscht wurden. –> ORM select-artige Queries löschen Flush aus!
Der SQL Select (direkt auf der DB) zeigt diese aber erst nach einem Commit!

PostgresSQL mit Python (psycopg2)

Setup

Administering PostgresSQL

Using PSQL commandline tool or PgAdmin GUI (included with the Windows installer PostgreSQL Database Download)
Der Pfad muss noch gesetzt werden um es aus dem Dos-Prompt heraus ausführen zu können.

PostgresSQL DB starten:

pg_ctl -D „C:\Program Files\PostgreSQL\13\data“ start
.. wobei der Pfad allenfall anzupassen ist! Siehe auch: Start/Stop PostgresSQL Server.

!template1 und postgres DBs sind nicht zum Verändern gedacht (ausser man will die DB Vorlage für neue DBs verändern)! Template1 DB ist – wie der Name schon sagt – ein Template für neu zu erstellendes DBs.

Postgres default port: 5432

postgres commands issued at the OS command line:

CommandDescription
sudo -u <username> -ilog in as username. Default installed user is called postgres
createdb <dbname>
dropdb <dbname>
select * from tableA;


PSQL

CommandDescription
psql <dbname> [<username>]Initial login to the db starting the PSQL interactive tool.
\llist all databases on the server, owners, access levels
\c <dbname>connect to a DB
\dtshow DB tables
\d <tablename>describe table
\qquit PSQL tool

Python access to PostgresSQL using psycopg2

import psycopg2

conn = psycopg2.connect('dbname=testDB user=postgres password=*****')
cursor = conn.cursor()

# Open a cursor to perform database operations
cur = conn.cursor()

# drop any existing todos table
cur.execute("DROP TABLE IF EXISTS todos;")

# (re)create the todos table
# (note: triple quotes allow multiline text in python)
cur.execute("""
  CREATE TABLE todos (
    id serial PRIMARY KEY,
    description VARCHAR NOT NULL
  );
""")

todos = ["Abwaschen", "Putzen", "Aufgabenhilfe", "Ferienplanung"]

for tup in enumerate(todos):
    cur.execute('insert into todos (id, description) values (%s, %s)', tup)

# Alternative: Parameter resolution with named parameters by providing an parameter object:
for tup in enumerate(todos, 10):
    cur.execute('insert into todos (id, description) values (%(key)s, %(value)s)', { 'key' : tup[0], 'value' : tup[1] })

cur.execute('select * from todos')
results = cur.fetchall()

print('Read from DB: ')
for res2 in results:
    print(res2)

# commit, so it does the executions on the db and persists in the db
conn.commit()

cur.close()
conn.close()

Python (Merkpunkte für den Java-Gewohnten)

Hierarchy of Online Resources

–> From Udacity training: Hierarchy of Online Resources

Ausführung

Python ist normalerweise im Windows enthalten. Also: Konsole öffnen, dann python eintippen und schon wartet der Python-Interpreter auf deine Kommandos.

Fancy Interpreter: Wenn der Standard Interactive Interpreter nicht genügt, wäre IPython eine konfortablerer Alternative.

Operators

Speziell:

CodeBedeutung
x**2x hoch 2

Variables and Assignment Operators

Variablen müssen nicht mit Typ deklariert werden.

CodeBedeutung
x, y, z = 3, 4, 5Werte werden der Reihe nach den variablen x, y, z zugeordnet.
i = 1Definition eines Int
f = 1.0Definition eines Float
i1 = int(f)Umwandlung Float zu Int
f1 = float(i)Umwandlung Int zu Float
boolNot ‚boolean‘!
type(i)Typenprüfung
print(type(x))Drucken des Typen
> print(.1 + .1 + .1 == .3)
False
Float hat nur diskrete Werte, kann also 0.1 nicht genau abbilden!
not (i1 > i2 or (i3 == i4 and i4 != i5))boolean expression demo 🙂

String

CodeBedeutung
this_string = 'Simon\'s skateboard is in the garage.'
this_string2 = "Simon\'s skateboard is in the garage.
String demo
>>> print("Hello" * 5) HelloHelloHelloHelloHello
>>> print(len("Hanspeter"))
9

„Hanspeter“[2]
–> „n“

print(‚Hanspeter ist so lang: ‚ + str(len(‚Hanspeter‘)))
Hanspeter ist so lang: 9
Int zu String Konvertierung
Nötig bei Print-Ausgabe
>>>my_string = „ab“
>>> my_string.islower()
True
>>> my_string.count('a')
2
>>> my_string.find('a')
3

firstName, lastName = „Max“, „Muster“
„Hello! My name is {} {}„.format(firstName, lastName)

String Interpolation Demo
>new_str = "The cow jumped over the moon." >new_str.split()
['The', 'cow', 'jumped', 'over', 'the', 'moon.']
Split demo.
A list is created.
new_str.split('.')Split with ‚.‘ as delimiter.
>“Nomen est omen“.find(‚om‘)
1
erstes Vorkommen finden
>“Nomen est omen“.rfind(‚om‘)
10
letztes Vorkommen finden
>“Nomen est omen“.count(‚omen‘)
2
Anzahl Vorkommen eruieren

Lists

CodeMeaning
list_of_random_things = [1, 3.4, 'a string', True]Listen könnne heterogenen Inhalt haben!
>>> list_of_random_things[0]
1
>>> list_of_random_things[-1]
True
Letztes Element der Liste selektieren!
>>> list_of_random_things = [1, 3.4, 'a string', True]
>>> list_of_random_things[1:2]
[3.4]
Range einer Liste extrahieren
>>> list_of_random_things[2:]
['a string', True]
End-Range einer Liste extrahieren
>>> list_of_random_things[:2]
[1, 3.4, 'a string']
Anfangs-Range einer Liste extrahieren
>>> 'this' in 'this is a string'
True
>>> 'in' in 'this is a string'
True
>>> 'isa' in 'this is a string'
False
>>> 5 not in [1, 2, 3, 4, 6]
True
>>> 5 in [1, 2, 3, 4, 6]
False
‚in‘ / ’not in‘ demo
len(list) returns how many elements are in a list.
max(list)returns the greatest element of the list. How the greatest element is determined depends on what type objects are in the list. The maximum element in a list of numbers is the largest number. The maximum elements in a list of strings is element that would occur last if the list were sorted alphabetically. This works because the the max function is defined in terms of the greater than comparison operator. The max function is undefined for lists that contain elements from different, incomparable types.
min(list) returns the smallest element in a list. min is the opposite of max, which returns the largest element in a list.
sorted(list)returns a copy of a list in order from smallest to largest, leaving the list unchanged.
„-„.join([„Anna“, „Maria“])
‚Anna-Maria‘
Join List Demo
>>>letters = ['a', 'b', 'c', 'd'] >>>letters.append('z') >>>print(letters)
['a', 'b', 'c', 'd', 'z']
Hinzufügen von objekten in die Liste
list1 = [„Hans“, „Karl“, „Guido“]
for s in enumerate(list1):
… print(s)

(0, ‚Hans‘)
(1, ‚Karl‘)
(2, ‚Guido‘)
Enumerate-Demo
Erstellen eines Iterable über Tupels, wobei das Tupen eine Fortlaufenden Sequenzunummer und den jeweiligen Wert aus der Liste enthält.
cities = [„amsterdam“, „paris“, „berlin“]
capitalizedCities = city.title() for city in cities
List Comprehension Demo
Action Block, Laufvariable, behandelte Liste
even_squares = n**2 for n in range(9) if n**2%2==0List Comprehension Demo mit Condition
nonsensList = n**2 if n%2 == 0 else „-„ for n in range(9)List Comprehension Demo mit Condition and Else value
list(iterator)Liste aus Iterator erstellen

Tuple

CodeMeaning
t1 = („Max“, „Muster“, „Zürich“) Tupel erstellen
t2 = „Max“, „Muster“, „Zürich“Tupel erstellen
vn, nn, ort = t1Tupel auspacken 1
vn = t1[0]Tupel auspacken 2
t1[2] = „Zürich“
Traceback (most recent call last):
File „“, line 1, in
TypeError: ‚tuple‘ object does not support item assignment
Tupel ist immutable?
listOfTupels = zip(listA, listB)Zip Demo
Erstellen eines Iterable über Tupels die jeweils einen Wert aus beiden Ursprungslisten enthalten.
for t in zip([„Karl“, „Lagerfeld“], [„Heidi“, „Klum“]):
… print(t)

(‚Karl‘, ‚Heidi‘)
(‚Lagerfeld‘, ‚Klum‘)
Zip example
Erstellen eines Iterable über Tupels die jeweils einen Wert aus beiden Ursprungslisten enthalten.

Sets

CodeMeaning
set1 = {„Hans“, „Karl“, „Guido“}Set erstellen
>list1 = [„Hans“, „Karl“, „Guido“, „Hans“]
>set2 = set(list1)
>set2
{‚Karl‘, ‚Guido‘, ‚Hans‘}
Set aus Liste erstellen
set2.add(„Hermann“)Hinzufügen

Dictionaries (Maps)

CodeMeaning
elements = {"Karl": 1, "Mark": 2, "John": 6}Set erstellen
print(elements["John"]) Zugriff
elements[„John“] = 77Update
>elements[„Inexisting_Name“]
Traceback (most recent call last):
File „“, line 1, in
KeyError: ‚Inexisting_Name‘
Error bei nicht gefundener Key
Besser:
>v1 = map1.get(‚Inexisting_Name‘)
>print(v1)
None
Oder (mit Default):
v1 = map1.get(‚Inexisting_Name‘, 99)
print(v1)
99
print(map1)
{‚Hans‘: 1, ‚Peter‘: 2}
>"Inexisting_Name" in elements
False
Präsenz-Test
map1[„Hermann“]
Traceback (most recent call last):
File „“, line 1, in
KeyError: ‚Hermann‘

Generators

Generators werden benutzt um einen Iterator zu definieren. Dazu wird eine Funktion programmiert, die yield Statements enthält. Der basierend auf dieser Funktion definierte Iterator durchläuft die Funktion dann bei jedem Next-Aufruf eine yield -Position weiter.

-> Udacity Explaination

Control Flow

CodeMeaning
if a > b:
doSomething()
!Der Block ist limitiert zu beginn durch das ‚:‘ und zum ende durch die Leerzeile!
Zeileneinzug ist obligatorisch!
if a > b:
doSomething()
elif a = b:
doSthOther()
else
for i in array1:
doSomething()
For-Loop-Demo
range(start, end[, stepWidth])
>for(i in range(1, 9)):
> print(i**2)
1
4
9
for k in dictionary: Keys der Map holen
for k,v in dict.items(): Key/Value Items der Map holen
for v in dict.values(9:Values der Map holen
while <condition>:
doSomething()
While-Loop-Demo
try:
# some code
except (ValueError, KeyboardInterrupt): # some code
finally
# some code
Try-Catch:
Except ohne Error-Angabe möglich
Mehrere Except-Blöcke mit unterschiedlichen Prozeduren möglich
try:
# some code
except Exception as e:
print("ZeroDivisionError occurred: {}".format(e))
Error-Message benutzen

Functions

CodeMeaning
>def cyl_vol(height, radius=5):
> return height * PI * radius**2
>
>cyl_vol(10)
785.72425
Function definition mit Defaultwert-Vorgabe
cyl_vol(radius=2, height=10)
Equivalent:
dyl_vol(10, 2)
call with named parameters
def cyl_vol(height, radius=5):
„““Berechnet das Zylinder-Volumen
INPUT:
height: float, höhe des Zylinders
radius: float, radius des Zylinders
OUTPUT:
float, berechnetes Volumen
„““
return height * PI * radius**2
Methoden-Dokumentation
height, radius: height * PI * radius**2Lambda definition
map(function, iterable)Map Definition
cities = [„amsterdam“, „berlin“, „rome“]
capitalized_cities = map(lambda c: c.title(), cities)
Map Demo
filter(filter_fn, iterator)Filter Definition
cities = [„amsterdam“, „berlin“, „rome“]
a_cities = filter(lambda c: c[0]==’a‘, cities)
Filter Demo

Scope:
Globale Variablen können nicht innerhalb einer Funktion verändert werden.

Scripting

CodeMeaning
>python script1.pyPython-Script ausführen
a = input(„Gib eine Zahl:“)
aQuadrat = int(a)**2
Einen wert von der Konsole einlesen
print(eval(„3**3“))
27
Eval-Funktion: Ein String wird als Python-Code interpretiert.

Files I/O

CodeMeaning
f = open('my_path/my_file.txt', 'r') file_data = f.read()
f.close()
Opening and reading a file
with open('my_path/my_file.txt', 'r') as f: file_data = f.read()… alternatively (including the close op)
f = open('my_path/my_file.txt', 'w') f.write("Hello there!") f.close()Write to a file (erases the preliminarlily existin content!)
# Open a file with access mode ‚a‘
file_object = open(’sample.txt‘, ‚a‘)

# Append ‚hello‘ at the end of file
file_object.write(‚hello‘)

# Close the file
file_object.close()
Append to an existing file
camelot_lines = []
with open("camelot.txt") as f:
for line in f:
camelot_lines.append(line.strip())
print(camelot_lines)
Read file, line by line
f = open('my_path/my_file.txt', 'r') file_data = f.readLine()
f.close()
.. alternatively

Imports/Libraries/Modules

CodeLabel
#This is a library file
def doSth():
# some code

def main():
# Code that runs only if this file is called directly by
# >python libraryfile.py
# –> see below how / when this function is called!

#Trick to evaluate if this file is called directly by
# >python libraryfile.py and only then call main()
if __name__ == '__main__':
main()
Library definition
(Trick to code main part there that is only called when it runs as root)
import useful_functions as uf

mean = uf.mean(scores)
Import of library in Main file

‚as uf‘ is optional
import random

print(random.randint(1,10))
Import der standard Random library
from ranwom import randint as rdInt
import doSth from sillylib
Similar as in Java:
import static com.lib.Myclass.doSth;
from mylib import *Do not use this!
import os.path
os.path.isdir(„mypath“)
Importing a Submodule or a Module
from datetime import datetimeImports a class from a module (both having the same name)
>python
>>>import myscript as my
>>>from myother import MyEntityClass, db
MyEntityClass.query.all()
Imports können selbstvertändlich auch innerhalb der python interaktiven Konsole gemacht werden. Damit ein eigenes File importiert werden kann, muss dessen Mame Python-Kompatibel sein (z.B. keine ‚-‚)
Import ohne „.py“-Endung!
Python Standard Libraries
vs.
3rd Pary Libraries
Usefull 3rd-Party Libraries
PipStandard Phython Package Manager
AnnacondaPython Package Manger specifically designed for Data Science
pip install package_namePackage ‚package_name‘ installieren
Danach kann es genau wie Python Standard Libs im Code benutzt werden.
requirements.txt:
meineLibrary==1.2.5
andereLibrary==9.30.3

>pip install -r requirements.txt
Definition aller Dependencies in einem Requirments-File und installieren derselben via PIP.