dict und dict zusammenführen...

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
stuhlbein
User
Beiträge: 89
Registriert: Freitag 9. Januar 2009, 16:08

Hallo! :)

Ich weiss dass ich diese Frage bereits im IRC channel mal gestellt habe, allerdings weiss ich wirklich nicht weiter hier.

Momentan nutz ich folgendes Skript um die datei /etc/passwd in Lesbarem Format wiederzugeben:

Code: Alles auswählen

import sys

class PasswdDumper:

    def readfile(self, f):
        try:
            data = open(f).read()
            return data
        except IOError, w:
            sys.stderr.write("Error Opening \"%s\" for reading: %s\n" % (f, w))
            sys.exit(1)

    def __init__(self, passwd_file="/etc/passwd", delim="="):
        data = self.readfile(passwd_file)
        for line in data.split("\n"):
            if line not in (None, ''):
                sb = line.split(':')
                print("USER        %s %s" % (delim, sb[0]))
                print("PASSWD      %s %s" % (delim, sb[1]))
                print("USER_ID     %s %s" % (delim, sb[2]))
                print("GROUP_ID    %s %s" % (delim, sb[3]))
                print("INFORMATION %s %s" % (delim, sb[4]))
                print("HOME        %s %s" % (delim, sb[5]))
                print("SHELL       %s %s" % (delim, sb[6]))
                print("---------------------------\n")


if __name__ == '__main__':
    if len(sys.argv) > 1:
        PasswdDumper(sys.argv[1])
    else:
        PasswdDumper()
Geplant war aber eigentlich mal, dass am ende ein Dict mit den werten der /etc/passwort "generiert" wird.

Aber hier fängt nun das eigentliche Problem an...: Ich weiss nicht, wie ich zwei Dicts zusammenführen soll, da diese ja notwendigerweise im Skript entstehen würden!

ps: ja, ich bin neu (im Forum ;))

greetz, bitfish
BlackJack

@Bitfish: Wo würden da zwangsläufig zwei `dict`\s entstehen!?

Anmerkungen zum Skript: Was soll die Klasse? Die ist völlig überflüssig -- das sind einfach nur zwei Funktionen.

Dateien, die man öffnet, sollte man auch explizit wieder schliessen oder die ``with``-Anweisung verwenden. Und in Funktionen/Methoden sollte man das Programm nicht einfach mit `sys.exit()` beenden. Damit kann man die Funktion schlechter wiederverwenden und schlechter testen.

In der Regel versucht man es zu vermeiden Textdateien komplett in den Speicher zu lesen, wenn man die Zeilen einzeln verarbeiten möchte. Dateiobjekte sind nämlich "iterables" über die Zeilen.

Wie soll ein `None` beim `split()`\en entstehen können? Was ist mit Leerzeilen die nicht ganz leer sind, sondern nur "whitespace"-Zeichen enthalten?

Wofür steht die Abkürzung `sb`?

Wenn man sich die ``print``\s anschaut und das Du da einen Index manuell in jeder Zeile "hochgezählt hinschreibst" legt die Verwendung einer Schleife nahe.

Code: Alles auswählen

from __future__ import with_statement
import sys

FIELD_NAMES = ['USER', 'PASSWD', 'USER_ID', 'GROUP_ID',
               'INFORMATION', 'HOME', 'SHELL']
MAX_FIELDNAME_LENGTH = max(map(len, FIELD_NAMES))


def iter_passwd(filename='/etc/passwd'):
    with open(filename, 'r') as lines:
        for line in (s.sstrip() for s in lines):
            if line:
                yield line.split(':')


def dump_passwd(rows, delimiter='='):
    for row in rows:
        for name, value in zip(FIELD_NAMES, row):
            print '%-*s %s %s' % (MAX_FIELDNAME_LENGTH, name, delimiter, value)
        print '-' * 30


def main():
    try:
        rows = iter_passwd(sys.argv[1]) if len(sys.argv) > 1 else iter_passwd()
    except IOError, error:
        sys.stderr.write('Error: %s\n' % error)
    else:
        dump_passwd(rows)


if __name__ == "__main__":
    main()
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

Moin,

das pwd-Modul parst die passwd bereits und kann eine Liste mit allen Einträgen zurückgeben. Allerdings ist es nicht so flexibel: Man kann keine passwd angeben (zumindest weiß ich nicht, wie). Außerdem liest es auch alle Daten in den Speicher. Wobei man das IMO bei der passwd auch vernachlässigen kann.

Gruß,
Manuel
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

helduel hat geschrieben:Allerdings ist es nicht so flexibel: Man kann keine passwd angeben (zumindest weiß ich nicht, wie).
Mir ist kein System bekannt dass seine ``passwd`` nicht in ``/etc/passwd`` hat.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

helduel hat geschrieben:das pwd-Modul parst die passwd bereits und kann eine Liste mit allen Einträgen zurückgeben. Allerdings ist es nicht so flexibel: Man kann keine passwd angeben (zumindest weiß ich nicht, wie).
Die braucht man auch nicht angeben. Das Modul nutzt die Funktionen aus der <pwd.h> und die funktionieren zuverlässig auf jeden System. Unter OSX beispielsweise stehen die Benutzer nicht in der /etc/passwd (es gibt die Datei zwar die wird aber nur im Single-User-Modus beachtet), das läuft über einen Open-Directory-Dienst. Da kommt man mit dem Auslesen von irgendwelchen Textdateien nicht weit.
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

Leonidas hat geschrieben:
helduel hat geschrieben:Allerdings ist es nicht so flexibel: Man kann keine passwd angeben (zumindest weiß ich nicht, wie).
Mir ist kein System bekannt dass seine ``passwd`` nicht in ``/etc/passwd`` hat.
Sein Code sieht das nunmal vor. Warum auch nicht? Er kann ja die passwds von verschiedenen Rechnern untersuchen/bearbeiten wollen. Wenn nicht, dann ist der Punkt natürlich irrelevant.

Gruß,
Manuel
stuhlbein
User
Beiträge: 89
Registriert: Freitag 9. Januar 2009, 16:08

helduel hat geschrieben:Moin,

das pwd-Modul parst die passwd bereits und kann eine Liste mit allen Einträgen zurückgeben. Allerdings ist es nicht so flexibel: Man kann keine passwd angeben (zumindest weiß ich nicht, wie). Außerdem liest es auch alle Daten in den Speicher. Wobei man das IMO bei der passwd auch vernachlässigen kann.

Gruß,
Manuel
Ah, dann war die ganze arbeit mehr oder weniger Umsonst :)

BlackJack hat geschrieben: @Bitfish: Wo würden da zwangsläufig zwei `dict`\s entstehen!?
Lies bitte die frage. Es entstehen keine dicts, es war geplant dass am ende ein Dict mit den werten der /etc/passwd generiert wird. Da ich aber nicht wusste wie ich das lösen soll, habe ich es bei einer einfachen Ausgabe belassen.
Anmerkungen zum Skript: Was soll die Klasse? Die ist völlig überflüssig -- das sind einfach nur zwei Funktionen.
Das ist richtig, aber Python ist eine Objekt Orientierte Sprache, und das ist für >mich< grund genug auch Klassen zu verwenden.
Dateien, die man öffnet, sollte man auch explizit wieder schliessen oder die ``with``-Anweisung verwenden. Und in Funktionen/Methoden sollte man das Programm nicht einfach mit `sys.exit()` beenden. Damit kann man die Funktion schlechter wiederverwenden und schlechter testen.

In der Regel versucht man es zu vermeiden Textdateien komplett in den Speicher zu lesen, wenn man die Zeilen einzeln verarbeiten möchte. Dateiobjekte sind nämlich "iterables" über die Zeilen.
Danke, ich werds mir merken ;)
Wie soll ein `None` beim `split()`\en entstehen können? Was ist mit Leerzeilen die nicht ganz leer sind, sondern nur "whitespace"-Zeichen enthalten?
Ist vielleicht eine Angewohnheit aus altn PHP zeiten, da PHP auch '' als NULL interpretiert (einer dieser WTF momente in PHP).

Wofür steht die Abkürzung `sb`?
Für nix, ich hätte vermutlich einen besseren Namen wählen können.
Wenn man sich die ``print``\s anschaut und das Du da einen Index manuell in jeder Zeile "hochgezählt hinschreibst" legt die Verwendung einer Schleife nahe.
Jo. :)
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Bitfish hat geschrieben:Das ist richtig, aber Python ist eine Objekt Orientierte Sprache, und das ist für >mich< grund genug auch Klassen zu verwenden.
Die Verwendung von Klassen macht Code nicht Objekt orientiert. Ein sehr gutes Beispiel ist dafür Java. Die Idee nur Klassen zu verwenden hat da zu allem geführt aber nicht zu OOP.
lunar

helduel hat geschrieben: Außerdem liest es auch alle Daten in den Speicher.
Woher weißt du das?
BlackJack

@Bitfish: Ich habe die Frage gelesen, darum steht in der Antwort bzw. Gegenfrage auch "würden" und nicht "werden".

Python ist eine *objekt*orientierte Programmiersprache, also reicht es völlig aus Funktions*objekte* zu erstellen. Alles sinnlos in Klassen zu stopfen macht ein Programm weder objektorientiert, noch besonders sauber oder verständlich.

Wenn man eine Klasse sieht, erwartet man eine Verbindung von Daten und dazugehörigen Operationen und nach der `__init__()` ein initialisiertes Exemplar von so einem Verbund, mit dem man dann sinnvolle Dinge anstellen kann. Wenn sich die `__init__()` wie eine Funktion verhält, und die Methoden nur Funktionen sind, und das Objekt was man erzeugt, überhaupt gar nicht verwendet wird, dann ist das überraschend und unsauber. Und eben nicht OOP.
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

lunar hat geschrieben:
helduel hat geschrieben: Außerdem liest es auch alle Daten in den Speicher.
Woher weißt du das?
Weil ich mit getpwall, was der Funktion entspricht, die hier nachgebaut werden soll, eine Liste mit allen Daten bekomme.
stuhlbein
User
Beiträge: 89
Registriert: Freitag 9. Januar 2009, 16:08

BlackJack hat geschrieben:@Bitfish: Ich habe die Frage gelesen, darum steht in der Antwort bzw. Gegenfrage auch "würden" und nicht "werden".
Sorry - hab ich wohl missverstanden ;)
Python ist eine *objekt*orientierte Programmiersprache, also reicht es völlig aus Funktions*objekte* zu erstellen. Alles sinnlos in Klassen zu stopfen macht ein Programm weder objektorientiert, noch besonders sauber oder verständlich.
Ich werds mir merken. Vielleicht bin ich einer dieser Javakranken... auch wenn ich nie mit Java arbeiten musste (zum glück :D).
Wenn man eine Klasse sieht, erwartet man eine Verbindung von Daten und dazugehörigen Operationen und nach der `__init__()` ein initialisiertes Exemplar von so einem Verbund, mit dem man dann sinnvolle Dinge anstellen kann. Wenn sich die `__init__()` wie eine Funktion verhält, und die Methoden nur Funktionen sind, und das Objekt was man erzeugt, überhaupt gar nicht verwendet wird, dann ist das überraschend und unsauber. Und eben nicht OOP.
So hab ichs noch nicht betrachtet - ergibt aber durchaus sinn. Vielleicht ist mein verständnis von OOP einfach durch falsche vorbilder getrübt ;)
Antworten