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
- Alembic (used by Flask-Migrate under the hood)
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-Typ | Handling (Python) |
---|---|
URL parameter: /foo?field1=value | value1 = request.args.get(field1) |
Form input | un = reqest.form.get(‚username‘) pw = request.form.get(‚password‘) |
application/json | data_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.
Ablauf | Command | Meaning |
---|---|---|
1 | >python | Start Python Console |
2 | >from path/flask_postgres_sql_hello_app import db,Person | Importiert die in flask_postgres_sql_hello_app.py (–> siehe) gemachten Definitionen von db und Person |
3ff | results = Person.query.all() | Holt alle Person Entitäten von der entsprechenden Tabelle |
3ff | results = Person.query.first() | |
3ff | Person.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) | |
3ff | Person.query.filter(Person.name==‚Hans‘).filter(Person.name==‚Peter‘).all() | Multiple Filters (Method chaining) |
3ff | query.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 | |
3ff | person = Person(name=’Bob‘) db.session.add(person) db.sesssion.commit() | Erstellen eines Person-Objekts und speichern desselben. |
3ff | db.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.p
y:
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.p
y 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
- Installation: Postgres Download page
- Installation psycopg2: install instructions found here
- Python
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 |
!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:
Command | Description |
---|---|
sudo -u <username> -i | log in as username. Default installed user is called postgres |
createdb <dbname> | |
dropdb <dbname> | |
select * from tableA; |
PSQL
Command | Description |
---|---|
psql <dbname> [<username>] | Initial login to the db starting the PSQL interactive tool. |
\l | list all databases on the server, owners, access levels |
\c <dbname> | connect to a DB |
\dt | show DB tables |
\d <tablename> | describe table |
\q | quit 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:
Code | Bedeutung |
---|---|
x**2 | x hoch 2 |
Variables and Assignment Operators
Variablen müssen nicht mit Typ deklariert werden.
Code | Bedeutung |
---|---|
x, y, z = 3, 4, 5 | Werte werden der Reihe nach den variablen x, y, z zugeordnet. |
i = 1 | Definition eines Int |
f = 1.0 | Definition eines Float |
i1 = int(f) | Umwandlung Float zu Int |
f1 = float(i) | Umwandlung Int zu Float |
bool | Not ‚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
Code | Bedeutung |
---|---|
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
Code | Meaning |
---|---|
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==0 | List 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
Code | Meaning |
---|---|
t1 = („Max“, „Muster“, „Zürich“) | Tupel erstellen |
t2 = „Max“, „Muster“, „Zürich“ | Tupel erstellen |
vn, nn, ort = t1 | Tupel 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
Code | Meaning |
---|---|
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)
Code | Meaning |
---|---|
elements = {"Karl": 1, "Mark": 2, "John": 6} | Set erstellen |
print(elements["John"]) | Zugriff |
elements[„John“] = 77 | Update |
>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.
Control Flow
Code | Meaning |
---|---|
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
Code | Meaning |
---|---|
>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**2 | Lambda 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
Code | Meaning |
---|---|
>python script1.py | Python-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
Code | Meaning |
---|---|
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
Code | Label |
---|---|
#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 datetime | Imports 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 |
Pip | Standard Phython Package Manager |
Annaconda | Python Package Manger specifically designed for Data Science |
pip install package_name | Package ‚package_name‘ installieren Danach kann es genau wie Python Standard Libs im Code benutzt werden. |
requirements.txt:meineLibrary==1.2.5 | Definition aller Dependencies in einem Requirments-File und installieren derselben via PIP. |