#! /usr/bin/env python3 import sys from pprint import pprint # from argv import argv_value import argv from utilities import hide_exception def read_file(path: str) -> "List of lines": # File-Objekt ist gleichzeitig Context-Manager, # schliesst beim Verlassen des Kontextes automatisch den File-Deskriptor with open(path, 'r') as f: # f.read(buflen) - binary read # f.readline() - 1 Textzeile lesen -> str # f.readlines() - alle Textzeilen lesen -> list # f ist gleichzeitig Iterator # 1. Variante: explizite for-Schleife lines = [] for line in f.readlines(): lines.append(line.rstrip()) # 2. Variante: Mit Hilfe von Lambda und f als Iterator #lines = list(map(lambda s: s.rstrip(), f)) # 3. Variante: Klassenfunktion rstrip und f als Iterator #lines = list(map(str.rstrip, f)) # 4. Variante: Mit List Comprehension und f als Iterator #lines = [line.rstrip() for line in f] return lines def parse_passwd_line(line: str) -> "Dict of passwd details": parts = line.split(':') # erzeugt List of Strings # userdict = {'username': parts[0], ...} # https://de.wikipedia.org/wiki/GECOS-Feld userdict = dict(username=parts[0], uid=int(parts[2]), gid=int(parts[3]), realname=parts[4].split(',')[0], gecos=parts[4], home=parts[5], shell=parts[6]) return userdict def build_userlist(lines) -> "List of user dicts": result = [] for line in lines: result.append(parse_passwd_line(line)) return result def print_userlist_sorted_by_username(userlist): # Sorted iteriert ueber die userlist und # ruft fuer jedes Element key(elem) auf # also e im Lambda-Ausdruck ist Element der Liste (also der Userdict) # Sorted baut Shadow-Liste mit Sortierkriterien auf for user in sorted(userlist, key=lambda e: e['username'].lower()): print(user['username'], user['uid'], user['realname']) def print_to_file(userlist): userlen = max(map(lambda u: len(u['username']), userlist)) try: with open('/etc/userlist.txt', 'w') as outfile: for user in userlist: print("{uid:5} {username:{width}} {realname}".format( width=userlen, **user), file=outfile) # Alle ImportError schlicht ignorieren, nicht einmal eine Meldung ausgeben except ImportError: pass # Dieser Teil ist auskommentiert, damit hide_exception ueberhaupt # eine Exception zum Verarbeiten abbekommt # except OSError as e: # print("Kann Datei nicht schreiben,", e, file=sys.stderr) else: print("Wird ausgefuehrt, wenn keine Exception ausgeloest wurde.") finally: print("Wird immer durchlaufen, unabhaengig von ausgeloesten Exceptions") def print_userlist_sorted_by_uid(userlist): userlen = max(map(lambda u: len(u['username']), userlist)) for user in sorted(userlist, key=lambda e: e['uid']): print("{uid:5} {username:{width}} {realname}".format(width=userlen, **user)) def main(): # Dictionary mit Ausgabe-Funktionen als Referenz output_functions = { 'pprint': pprint, 'logger': print_to_file, 'username': print_userlist_sorted_by_username, 'uid': print_userlist_sorted_by_uid, } # Zum Test diese spezielle Ausgabe-Funktion verwenden # 'username' kommt spaeter von der Kommandozeile # outfunc = output_functions['username'] # outfunc = output_functions['uid'] outfunc = output_functions[argv.argv_value('-o', 'uid')] lines = read_file("/etc/passwd") userlist = build_userlist(lines) # print(userlist) # Kontrollausgabe outfunc(userlist) hide_exception(main)