(c) 2023 Technische Hochschule Augsburg - Fakultät für Informatik - Prof.Dr.Nik Klever - Impressum
Das reprlib-Modul stellt eine Version von repr() zur Verfügung, die für eine abgekürzte Anzeige mittels ... von großen oder tief verschachtelten Containern angepasst ist:
import reprlib
reprlib.repr(set('supercalifragilisticexpialidocious'))
"{'a', 'c', 'd', 'e', 'f', 'g', ...}"
The pprint module offers more sophisticated control over printing both built-in and user defined objects in a way that is readable by the interpreter. When the result is longer than one line, the “pretty printer” adds line breaks and indentation to more clearly reveal data structure:
Das pprint-Modul bietet eine ausgefeiltere Kontrolle über das Drucken von eingebauten und benutzerdefinierten Objekten, die vom Interpreter lesbar ist. Wenn das Ergebnis länger als eine Zeile ist, fügt der "hübsche Drucker" Zeilenumbrüche und Einrückungen hinzu, um die Datenstruktur deutlicher zu zeigen:
import pprint
t = [[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta','yellow'], 'blue']]]
pprint.pprint(t, width=30)
[[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta', 'yellow'], 'blue']]]
Das textwrap-Modul formatiert Textabschnitte, um diese an eine bestimmte Bildschirmbreite anzupassen:
import textwrap
doc = """The wrap() method is just like fill() except that it returns
a list of strings instead of one big string with newlines to separate
the wrapped lines."""
print(textwrap.fill(doc, width=40))
The wrap() method is just like fill() except that it returns a list of strings instead of one big string with newlines to separate the wrapped lines.
Das Modul locale greift auf eine Datenbank mit länderspezifischen Datenformaten zu. Das Gruppierungsattribut der Formatfunktion des Moduls locale bietet z.B. eine direkte Möglichkeit, Zahlen gruppiert mit entsprechenden länderspezifischen Separatoren zu formatieren:
import locale
locale.setlocale(locale.LC_ALL, 'de_DE.UTF-8')
conv = locale.localeconv() # get a mapping of conventions
x = 1234567.8
locale.format("%d", x, grouping=True)
'1.234.567'
locale.format_string("%s%.*f", (conv['currency_symbol'],conv['frac_digits'], x), grouping=True)
'€1.234.567,80'
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
conv = locale.localeconv() # get a mapping of conventions
x = 1234567.8
locale.format("%d", x, grouping=True)
'1,234,567'
locale.format_string("%s%.*f", (conv['currency_symbol'],conv['frac_digits'], x), grouping=True)
'$1,234,567.80'
Das Modul string enthält eine umfangreiche Klasse Template mit einer einfachen Syntax, die für eine Bearbeitung durch Endbenutzer geeignet ist. Dies ermöglicht es Endbenutzern, ihre Anwendungen anzupassen, ohne die Anwendung selbst ändern zu müssen.
Das Format verwendet Platzhalter, die mit einem vorangestellten $-Zeichen und anschliessenden gültigen Python-Identifikatoren (alphanumerische Zeichen und Unterstriche) gebildet werden. Werden die Platzhalter mit geschweiften Klammern umgeben, können weitere alphanumerische Zeichen ohne zusätzliche Zwischenräume folgen. Ein doppeltes $ $ erzeugt ein einziges Escape-Zeichen $:
from string import Template
t = Template('${village}folk send $$10 to $cause.')
t.substitute(village='Nottingham', cause='the ditch fund')
'Nottinghamfolk send $10 to the ditch fund.'
Die Methode substitute() wirft einen KeyError, wenn ein Platzhalter nicht in einem Dictionary oder einem Keyword-Argument bereitgestellt wird. Bei Anwendungen, bei denen die vom Benutzer bereitgestellten Daten unvollständig sein können (wie z.B. bei Serienbrief-Anwendungen) kann die Methode safe_substitute() geeigneter sein - diese Methode lässt Platzhalter unverändert, wenn Daten fehlen:
t = Template('Return the $item to $owner.')
d = dict(item='unladen swallow')
t.substitute(d)
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-10-aa21a55b2069> in <module>() 1 t = Template('Return the $item to $owner.') 2 d = dict(item='unladen swallow') ----> 3 t.substitute(d) /home/root/anaconda3/lib/python3.6/string.py in substitute(*args, **kws) 124 raise ValueError('Unrecognized named group in pattern', 125 self.pattern) --> 126 return self.pattern.sub(convert, self.template) 127 128 def safe_substitute(*args, **kws): /home/root/anaconda3/lib/python3.6/string.py in convert(mo) 117 named = mo.group('named') or mo.group('braced') 118 if named is not None: --> 119 return str(mapping[named]) 120 if mo.group('escaped') is not None: 121 return self.delimiter KeyError: 'owner'
t.safe_substitute(d)
'Return the unladen swallow to $owner.'
Unterklassen der Klasse Template können ein benutzerdefiniertes Trennzeichen angeben. Beispielsweise kann ein Skript zur Umbenennung von Bildern für einen Fotobrowser das Prozentzeichen als Trennzeichen hernehmen um Platzhalter wie das aktuelle Datum, die Bildsequenznummer oder das Dateiformat damit verwenden zu können:
import time, os.path
photofiles = ['img_1074.jpg', 'img_1076.jpg', 'img_1077.jpg']
class BatchRename(Template):
delimiter = '%'
fmt = input('Enter rename style (%d-date %n-seqnum %f-format): ')
t = BatchRename(fmt)
date = time.strftime('%d%b%y')
for i, filename in enumerate(photofiles):
base, ext = os.path.splitext(filename)
newname = t.substitute(d=date, n=i, f=ext)
print('{0} --> {1}'.format(filename, newname))
Enter rename style (%d-date %n-seqnum %f-format): Test_%n.jpg img_1074.jpg --> Test_0.jpg img_1076.jpg --> Test_1.jpg img_1077.jpg --> Test_2.jpg
Eine weitere Anwendung für das Templating ist die Trennung der Programmlogik von den Details mehrerer und unterschiedlicher Ausgabeformate. Damit werden benutzerdefinierte Vorlagen für XML-Dateien, Klartextberichte und HTML-Webberichte möglich.
%%Mooc MoocStringAssessment
Verändern sie den Code in Zeile 11 in der obigen Zelle so, dass zusätzlich noch der ursprüngliche Name der Datei über den folgenden Input verwendet werden kann:
fmt = input('Enter rename style (%b-basename %d-date %n-seqnum %f-format): ')
Das Modul struct bietet die pack()- und unpack()-Funktionen für die Bearbeitung von binären Daten mit variabler Länge. Das folgende Beispiel zeigt, wie man Header-Informationen in einer ZIP-Datei durchlaufen kann, ohne das Modul zipfile zu verwenden.
Eine ZIP-Datei hat für jede komprimierte Datei den folgenden Aufbau als Fileheader (s. ZIP-Format bzw. auch Wikipedia)
local file header signature 4 bytes (0x04034b50)
version needed to extract 2 bytes
general purpose bit flag 2 bytes
compression method 2 bytes
last mod file time 2 bytes
last mod file date 2 bytes
crc-32 4 bytes
compressed size 4 bytes
uncompressed size 4 bytes
file name length 2 bytes
extra field length 2 bytes
file name (variable size)
extra field (variable size)
In dem Modul struct werden für die binären Strukturen Formatcharacter verwendet, die in der Modul-Dokumentation im Kapitel 7.1.2.2 aufgelistet sind. Dabei repräsentieren die im folgenden Code (Zeile 9) verwendeten "H" und "I" Kodierungen jeweils zwei und vier Byte unsignierte Zahlen und das "<"-Zeichen bedeutet, dass die Standardgröße verwendet und die Daten in der Reihenfolge Little-Endian-Byte sind:
import struct
with open('Bsp.zip', 'rb') as f:
data = f.read()
start = 0
for i in range(5):
# Beginn des 30 Byte Fileheaders
fields = struct.unpack('<IHHHHHIIIHH', data[start:start+30])
header = dict(zip(["signature", "version", "flag", "comp_method", "last_mod_time", "last_mod_date",
"crc32", "comp_size", "uncomp_size", "filenamesize", "extra_size"],fields))
# Beginn des variablen Filenamens
start += 30
filename = str(data[start:start+header["filenamesize"]],encoding='UTF-8')
# Beginn des variablen Extra Feldes
start += header["filenamesize"]
extra = data[start:start+header["extra_size"]]
# Ausgabe
print("{filename:32} - {comp_method:02x}, {last_mod_time:6}, {last_mod_date:6}, {crc32:08x}, {comp_size:6}, {uncomp_size:8}".format(filename=filename,**header))
# Beginn des nächsten Fileheaders
start += header["extra_size"] + header["comp_size"]
Aufgabe-Lösungsvorschlag.ipynb - 08, 45181, 19121, b9c3410d, 13513, 262708 Funktionale Programmierung.ipynb - 08, 40975, 19107, 492ab107, 1379, 7848 Generatoren.ipynb - 08, 9314, 19113, d4b49e2e, 23113, 141781 Iteratoren.ipynb - 08, 40973, 19107, ddd01fe2, 1872, 15234 Beispiele zu Generatoren.ipynb - 08, 16387, 19115, f01a27e4, 5915, 41640
!unzip -v Bsp.zip
Archive: Bsp.zip Length Method Size Cmpr Date Time CRC-32 Name -------- ------ ------- ---- ---------- ----- -------- ---- 262708 Defl:N 13513 95% 2017-05-17 22:03 b9c3410d Aufgabe-Lösungsvorschlag.ipynb 7848 Defl:N 1379 82% 2017-05-03 20:00 492ab107 Funktionale Programmierung.ipynb 141781 Defl:N 23113 84% 2017-05-09 04:35 d4b49e2e Generatoren.ipynb 15234 Defl:N 1872 88% 2017-05-03 20:00 ddd01fe2 Iteratoren.ipynb 41640 Defl:N 5915 86% 2017-05-11 08:00 f01a27e4 Beispiele zu Generatoren.ipynb -------- ------- --- ------- 469211 45792 90% 5 files
Wie verhält sich jetzt die Ausgabe des Datums (z.B. 19121) und der Uhrzeit (z.B. 45181) in der vorhergehenden Zelle zu der Ausgabe in dieser Zelle (Datum 2017-05-17 und Uhrzeit 22:03) ?
siehe Bits und Bytes im Unterkapitel [Zahlen und Zeichendarstellung](SE2016FS01/Skript/chapter/Grundlagen/Zahlen und Zeichendarstellung.ipynb) sowie Bit-Operatoren im Unterkapitel Operatoren
Um das Datum in 2 Bytes zu speichern, wird der Tag (1-31 oder 0-30) in 5 Bits, der Monat (0-11 oder 1-12) in 4 Bits und das Jahr in 7 Bits abgespeichert, somit erhält man folgende Formel:
datum = (jahr-1980) << 9 | monat << 5 | tag
Hierbei wird normiert auf das Jahr 1980 (Epoche genannt), sodass im Zeitraum zwischen 1980 und 2127 keine Probleme entstehen.
aus der obigen Beschreibung kann man mit den entsprechenden Masken die Umkehrung folgern:
tag = datum & 0b00011111 # 0x1f = 0b00011111 (5 Bits)
monat = (datum >> 5) & 0b00001111 # 0x0f = 0b00001111 (4 Bits)
jahr = ((datum >> 9) & 0b01111111) + 1980 # 0x7f = 0b01111111 (7 Bits)
Um die Uhrzeit in 2 Bytes zu speichern, werden 2 Sekunden durch 5 Bits, die Minuten durch 6 Bits und die Stunden wieder durch 5 Bits abgespeichert, somit erhält man analog
uhrzeit = stunden << 11 | minuten << 5 | sekunden // 2
woraus sich dann auch die Umkehrung ergibt:
sekunden = (uhrzeit & 0b00011111) * 2 # 0x1f = 0b00011111 (5 Bits)
minuten = (uhrzeit >> 5) & 0b00111111 # 0x3f = 0b00111111 (6 Bits)
stunden = (uhrzeit >> 11) & 0b00011111 # 0x1f = 0b00011111 (5 Bits)
import struct
with open('Bsp.zip', 'rb') as f:
data = f.read()
start = 0
for i in range(5):
# Beginn des 30 Byte Fileheaders
fields = struct.unpack('<IHHHHHIIIHH', data[start:start+30])
header = dict(zip(["signature", "version", "flag", "comp_method", "last_mod_time", "last_mod_date",
"crc32", "comp_size", "uncomp_size", "filenamesize", "extra_size"],fields))
# Beginn des variablen Filenamens
start += 30
filename = str(data[start:start+header["filenamesize"]],encoding='UTF-8')
# Beginn des variablen Extra Feldes
start += header["filenamesize"]
extra = data[start:start+header["extra_size"]]
# Berechnung des Datums
tag = header["last_mod_date"] & 0x1f
monat = (header["last_mod_date"] >> 5) & 0x0f
jahr = ((header["last_mod_date"] >> 9) & 0x7f) + 1980
# Berechnung der Uhrzeit
sekunden = (header["last_mod_time"] & 0x1f) * 2
minuten = (header["last_mod_time"] >> 5) & 0x3f
stunden = (header["last_mod_time"] >> 11) & 0x1f
# Ausgabe
print("{filename:32} - {comp_method:02x}, {last_mod_time:6}, {last_mod_date:6}, {crc32:08x}, {comp_size:6}, {uncomp_size:8}, {jahr}-{monat:02}-{tag:02}, {stunden:02}:{minuten:02}".format(filename=filename,tag=tag,monat=monat,jahr=jahr,stunden=stunden,minuten=minuten,**header))
# Beginn des nächsten Fileheaders
start += header["extra_size"] + header["comp_size"]
Aufgabe-Lösungsvorschlag.ipynb - 08, 45181, 19121, b9c3410d, 13513, 262708, 2017-05-17, 22:03 Funktionale Programmierung.ipynb - 08, 40975, 19107, 492ab107, 1379, 7848, 2017-05-03, 20:00 Generatoren.ipynb - 08, 9314, 19113, d4b49e2e, 23113, 141781, 2017-05-09, 04:35 Iteratoren.ipynb - 08, 40973, 19107, ddd01fe2, 1872, 15234, 2017-05-03, 20:00 Beispiele zu Generatoren.ipynb - 08, 16387, 19115, f01a27e4, 5915, 41640, 2017-05-11, 08:00
%%Mooc Video
%%Mooc WebReference
https://docs.python.org/3/tutorial/stdlib2.html
Hinweis: Kurze Auflistung einiger weiterer Module aus der Standardbibliothek
%%Mooc WebReference
https://docs.python.org/3/library/struct.html
Hinweis: struct — Interpretation von Bytes als gepackte Binärdaten