Seite 1 von 1

Das Aktualisieren einer Aliases Datei mit Hilfe von Python

Verfasst: Donnerstag 11. April 2013, 09:44
von Twinhand
Hallo zusammen,
ich habe mich gerade im Forum angemeldet, da ich aus den Einträgen im Internet nicht wirklich schlau werde.
Ich bin neu in der Programmierung, vorallem was Python angeht. Nun habe ich aber während meiner Ausbildung ein Python-Skript
bekommen, das ich mit einigen Funktionen editieren soll und Fehler ausmerzen soll. Zu einer der Funktionen gehört auch das automatische Aktualisieren einer Aliases Datei. ( Der Code den ihr gleich seht ist nicht von mir, ich habe nur einige Kommentare für mein eigenes Verständnis hinzugefügt.) Auf jeden Fall wird folgender Fehler ausgeworfen:
"ValueError: need more than 1 value to unpack"
Ich verstehe zwar was dieser Fehler in etwa bedeutet, habe aber keine Ahnung wie ich das beheben, bzw. anders machen sollte.
Ich bin mir sicher das ihr mir helfen könnt. Und ich würde euch bitten das was ihr als Lösung vorschlagt für "Idioten" zu erklären.^^
Ich danke euch schonmal im voraus. Hier sind noch einige Informationen die für euch nützlich sein könnten:


Inhalt der Test-Aliases Datei:

1: 0, 3, 5, afdas
2: 1, 2, 3, ads
3: 3, 2, 1, asd
4: 4, 5, 1, aff
5: 5, 2, 4, gdafg


Python Codeausschnitt:

Code: Alles auswählen

        aliasesFile = open("aliases", "r")                                      # *Zeile 214 open the aliases file which was safed in the "get_aliases" Shellscript with read access

        aliasesFileContents = aliasesFile.read().splitlines()                   # Read file into array, line by line

        aliasesFile.close()

        lines = [0]
        currentLine = 0                                                         # The current line is the first line in the script

        for line in aliasesFileContents:
            group, users = line.split(":")                                      #   <--- Fehler Zeile 224 Read group data into group and user data into users

            users = users.split(", ")                                           # split the users data into every user data

            if userform.GetInput("Username") in users:                          # If user is in group
                users.remove(username.GetInput("Username"))                     # Remove user from user data

            users = ", ".join(users)                                            # Write users line again

            lines.append(group + ": " + users)                                  # Overwrite current line

            currentLine = currentLine + 1

        lines = "\n".join(lines)

        outFile = open("aliases", "w")                                          # Overwrite file
        outFile.write(lines)
        outFile.close()


Entschuldige, dass wurde in Eile geschrieben. Der Fehler tritt laut Fehlermeldung nach oder während folgender Zeiler auf:

Code: Alles auswählen

group, users =line.split(":")

Traceback:

Code: Alles auswählen

localhost> localhost> localhost> setaclmailbox: super98: lrswipc: Mailbox does not exist
localhost> setaclmailbox: super98: lrswipc: Mailbox does not exist
localhost> [sudo] password for twinhand: 
newaliases: Aliases are not used in sSMTP
Connection to xxx.xxx.x.xxx closed.
Fetching file from remote host.
[sudo] password for twinhand: 
1: 0, 3, 5, afdas
2: 1, 2, 3, ads
3: 3, 2, 1, asd
4: 4, 5, 1, aff
5: 5, 2, 4, gdafg

Connection to xxx.xxx.x.xxx closed.
Success!

Traceback (most recent call last):
  File "mais-tools.py", line 5, in <module>
    application.Run()
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/application.py", line 43, in Run
    self.Menu()
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/application.py", line 39, in Menu
    self.mainMenu.GetInput()
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/library/gui/menu.py", line 70, in GetInput
    command[1]()
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/application.py", line 21, in <lambda>
    self.mainMenu.AddItem("u", "User Management", lambda:functions.usermanagement.Module(self))
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/usermanagement/__init__.py", line 11, in __init__
    self.Menu()
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/usermanagement/__init__.py", line 20, in Menu
    menu.GetInput()
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/library/gui/menu.py", line 70, in GetInput
    command[1]()
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/usermanagement/__init__.py", line 16, in <lambda>
    menu.AddItem("r", "Remote", lambda:functions.usermanagement.remote.Remote(self))
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/usermanagement/remote.py", line 12, in __init__
    self.Login()
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/usermanagement/remote.py", line 49, in Login
    self.Menu()
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/usermanagement/remote.py", line 23, in Menu
    menu.GetInput()
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/library/gui/menu.py", line 70, in GetInput
    command[1]()
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/usermanagement/remote.py", line 17, in <lambda>
    menu.AddItem("r", "Automated user registration", lambda:AutomatedUser(self))
  File "/media/data/twinhard/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/usermanagement/remote.py", line 168, in __init__
    self.Menu()
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/usermanagement/remote.py", line 177, in Menu
    menu.GetInput()
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/library/gui/menu.py", line 70, in GetInput
    command[1]()
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/usermanagement/remote.py", line 172, in <lambda>
    menu.AddItem("a", "Add User", lambda:self.AddUser())
  File "/media/data/twinhand/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/usermanagement/remote.py", line 224, in AddUser
    group, users = line.split(":")                                      # Read group data into group and user data into users
ValueError: need more than 1 value to unpack


nochmals vielen Dank

MfG
Twinhand

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Donnerstag 11. April 2013, 10:01
von Sirius3
Hallo und willkommen,

es gibt über diesem Editierfeld einen Knopf |python|, damit der Code schön formatiert wird. Insbesondere die Einrückungen sind in Python ja wichtig.
Es wäre hilfreich wenn Du den gesamten Traceback, insbesondere die Zeilennummer, in der der Fehler auftritt, posten würdest. So muß ich raten, wo der Fehler auftritt.
In Zeilen, die keinen Doppelpunkt enthalten fürt der Split zu einem Fehler, weil Python nicht weiß, was er users zuweisen soll.

Code: Alles auswählen

for line in aliasesFileContents:
    line = line.strip()
    if not line:
        pass # do noting
    elif ':' not in line:
        print "Wrong line format, ':' missing in '%s'"%line
    else:
        group, users = line.split(":") # Read group data into group and user data into users
        usw.

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Donnerstag 11. April 2013, 11:06
von Twinhand
Hallo Sirius 3 , danke für die schnelle Antwort, ich habe deine Bitten schnell in die Tat umgesetzt und deinen Vorschlag befolgt.
Allerdings kommt beim starten des Skripts folgende Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "mais-tools.py", line 1, in <module>
    import functions
  File "/media/data/kevin/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/__init__.py", line 1, in <module>
    import functions.application
  File "/media/data/kevin/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/application.py", line 4, in <module>
    import functions.usermanagement
  File "/media/data/kevin/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/usermanagement/__init__.py", line 4, in <module>
    import functions.usermanagement.remote
  File "/media/data/kevin/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/usermanagement/remote.py", line 228
    print "Wrong line format, ':' missing in '%s'"%line
                                                 ^
SyntaxError: invalid syntax
Und nein ich habe keinen Schreibfehler gemacht, ich habe es mehrmal kontrolliert.^^

MfG
Kevin Bouhsard

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Donnerstag 11. April 2013, 11:15
von kbr
@twinhand: Du hast offensichtlich zwei Fehlerquellen. Einmal, wie Sirius3 schon schrieb, in der alias-Datei, in der mindestens eine Zeile nicht dem Schema zu entsprechen scheint, dass vom Programm erwartet wird. Dies könntest Du bspw. mit try/except abfangen. Und dann ein Syntaxfehler, der sich in remote.py bemerkbar macht. Diesen Code sehen wir hier nicht.

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Donnerstag 11. April 2013, 11:23
von Twinhand
@kbr : Der Syntaxfehler ist erst aufgetreten als ich den Code den mir Sirius3 geschrieben habe hinzugefügt habe. Der Code bei dem der Fehler auftritt ist der oben genannte Code, so wie von Sirius3 vorgeschlagen angepasst.
Zu dem Fehler der in meinen ersten Post angezeigt wird, ich habe in einigen Webseiten gelesen das die Zahl von gelesenen Zeile und zurückgebeben Zeilen unterschiedlich ist. bzw. die Zeilen unterschiedlich groß sind ( klar haben die Unterschiede sonst müsste ich mir den Stress nicht machen) aber habt ihr eine Ahnung was man da machen könnte.
Die Beispiel Aliases Datei die ich zum Testen verwende ist in meinem ersten Post angezeigt. Und der Code deklariert doch genau das was in der Aliases Datei steht, also das Schema. Oder Irre ich mich?
MfG
Twinhand

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Donnerstag 11. April 2013, 11:30
von kbr
@twinhand: verstehe, ich hatte zu oberflächlich gelesen. Aber in Sirius3s Code-Schnippsel sehe ich auf Anhieb keinen Fehler.

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Donnerstag 11. April 2013, 11:39
von kbr
Twinhand hat geschrieben:Zu dem Fehler der in meinen ersten Post angezeigt wird, ich habe in einigen Webseiten gelesen das die Zahl von gelesenen Zeile und zurückgebeben Zeilen unterschiedlich ist. bzw. die Zeilen unterschiedlich groß sind ( klar haben die Unterschiede sonst müsste ich mir den Stress nicht machen) aber habt ihr eine Ahnung was man da machen könnte.
Die Beispiel Aliases Datei die ich zum Testen verwende ist in meinem ersten Post angezeigt. Und der Code deklariert doch genau das was in der Aliases Datei steht, also das Schema. Oder Irre ich mich?
Solange der Dateiinhalt nicht den Arbeitsspeicher sprengt, wird er von Deinem Programm komplett eingelesen. Diese Datei muss sich aber keineswegs an das Format halten, dass vom Programm erwartet wird. Mit der gezeigten Fehlerbehandlung wird lediglich das Programm robuster gemacht. Der eigentliche Fehler liegt in der zu lesenden Datei. Da würde ich mal rein schauen.
Vielleicht war es ja eine Leerzeile, dann bräuchtest Du jetzt nur noch den Syntaxfehler beheben, der nach dem Einfügen von Sirius3s Code aufgetreten ist.

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Donnerstag 11. April 2013, 11:44
von Twinhand
@kbr Ich sowieso nicht, soweit ich sehe liegt der Syntaxfehler laut dem Traceback an der Zeile mit print.
Wenn ich diese Zeile komplett weglasse wird allerding ein anderer Fehler ausgegeben und zwar folgender:

Code: Alles auswählen


  File "/media/data/kevin/Wichtige Inhalte/Bashscript zum anlegen und löschen von benutzern/mais-tools2/functions/usermanagement/remote.py", line 229
    else
       ^
IndentationError: expected an indented block
(Zeile 229 betrifft den nächsten Codeschnipsel unter der "print" Zeile.)
Un die zu lesende Datei ist wie gesagt folgende:
1: 0, 3, 5, afdas
2: 1, 2, 3, ads
3: 3, 2, 1, asd
4: 4, 5, 1, aff
5: 5, 2, 4, gdafg

Ich sehe aber einfach nicht was an dieser Datei unverständlich für das Programm sein könnte.

/
So sieht die Datei jetzt mit Sirius 3 s Code aus

Code: Alles auswählen

        aliasesFile = open("aliases", "r")                                      # open the aliases file which was safed in the "get_aliases" Shellscript with read access

        aliasesFileContents = aliasesFile.read().splitlines()                   # Read file into array, line by line

        aliasesFile.close()

        lines = []
        currentLine = 0                                                         # The current line is the first line in the script

        for line in aliasesFileContents:
            line = line.strip()
            if not line:
                pass
            elif ':' not in line:
                print "Wrong line format, ':' missing in '%s'"%line
            else:

                group, users = line.split(":")                                      # Read group data into group and user data into users

                users = users.split(", ")                                           # split the users data into every user data

            if userform.GetInput("Username") in users:                          # If user is in group
                users.remove(username.GetInput("Username"))                     # Remove user from user data

            users = ", ".join(users)                                            # Write users line again

            lines.append(group + ": " + users)                                  # Overwrite current line

            currentLine = currentLine + 1

        lines = "\n".join(lines)

        outFile = open("aliases", "w")                                          # Overwrite file
        outFile.write(lines)
        outFile.close()


MfG
Twinhand

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Donnerstag 11. April 2013, 12:23
von Twinhand
Hmm Update: Ok ich bin ein Idiot, in der Beispieldatei war natürlich ein Fehler ein Leerzeile. Nach korrigieren wirft mit das Terminal allerding folgenden Fehler aus:

Code: Alles auswählen

localhost> localhost> localhost> setaclmailbox: super99: lrswipc: Mailbox does not exist
localhost> setaclmailbox: super99: lrswipc: Mailbox does not exist
localhost> [sudo] password for kevin: 
newaliases: Aliases are not used in sSMTP
Connection to 192.168.1.220 closed.
Fetching file from remote host.
[sudo] password for kevin: 
1: 0, 3, 5, afdas
2: 1, 2, 3, ads
3: 3, 2, 1, asd
4: 4, 5, 1, aff
5: 5, 2, 4, gdafg
Connection to 192.168.1.220 closed.
Success!
[sudo] password for kevin: 
cp: Aufruf von stat für »/home//aliases“ nicht möglich: Datei oder Verzeichnis nicht gefunden
Connection to 192.168.1.220 closed.
(Auch wenn das vielleicht nicht in dieses Forum gehört, poste ich trozdem mal die subprozesse die das Skript ausführt, die mit diesem Pythoncode zu tun haben.

Code: Alles auswählen

elif [ "$OPTION" = "add_cyrus_user" ]; then
	if [ "$7" = "y" ]; then
		sshpass -p "$PASSWORD" ssh -tt -oStrictHostKeyChecking=no \
			$USERNAME@$HOST \
			"
			echo -e \"$UPASSWORD\ncm user.$UUSERNAME\nsam kontakt $UUSERNAME lrswipc\nsam seminar $UUSERNAME lrswipc\nexit\" | cyradm --user cyrus localhost  &&
			sudo sed  -i -r \"s/^($UGROUPS):(.*)/\1:\2, $UUSERNAME/g\" /etc/aliases && sudo newaliases
			" && exit 0


	else
		sshpass -p "$PASSWORD" ssh -tt -oStrictHostKeyChecking=no \
			$USERNAME@$HOST \
			"
			echo -e \"$UPASSWORD\ncm user.$UUSERNAME\nexit\" | cyradm --user cyrus localhost
			" && exit 0
	fi
elif [ "$OPTION" = "get_aliases" ]; then
	printf "Fetching file from remote host.\n" &&
	sshpass -p "$PASSWORD" ssh -tt -oStrictHostKeyChecking=no \
		$USERNAME@$HOST \
		"
		sudo cat /etc/aliases
		" | tee aliases &&
		printf "Success!\n" && exit 0
elif [ "$OPTION" = "push_aliases" ]; then
	sshpass -p "$PASSWORD" scp aliases $USERNAME@$HOST:/home/$USERNAME &&
	sshpass -p "$PASSWORD" ssh -tt -oStrictHostKeyChecking=no \
			$USERNAME@$HOST \
			"
			echo \"$UPASSWORD\" | sudo cp /home/$UUSERNAME/aliases /etc/aliases
			" &&
	printf "Copied file.\n" && exit 0

elif [ "$OPTION" = "delete_cyrus_user" ]; then
	#echo $UUSERNAME
 	sshpass -p "$PASSWORD" ssh  -tt -oStrictHostKeyChecking=no \
 		$USERNAME@$HOST \
 		"
 		echo -e \"lm\nsam user.$UUSERNAME cyrus c\ndm user.$UUSERNAME\nexit\" | cyradm --user cyrus localhost
		"
	exit $?
fi
add_add_cyrus_user und get_aliases wird genau vor dem bereits genannten Pythoncode per subprocess.call aufgerufen.
und push_aliases wird nach den oben genannten Pythoncode per subprocess.call aufgerufen.


MfG
Twinhand

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Donnerstag 11. April 2013, 12:28
von BlackJack
@Twinhand: Ist ``$UUSERNAME`` denn richtig oder sollte das nicht vielleicht ``$USERNAME`` heissen?

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Donnerstag 11. April 2013, 13:11
von Twinhand
Entschuldigung, das hätte ich dazu schreiben müssen, ja UUSERNAME ist die richtige Variable. Ist etwas ungeschickt gewählt ich weiß^^ Aber der USERNAME ist die Variable mit der man sich per ssh an dem Remote Host einloggt und der UUSERNAME ist der Nutzer der Tatsächlich eingetragen werden soll.

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Donnerstag 11. April 2013, 13:41
von Twinhand
Aktualisierung:
Also ich habe das Programm jetzt so weit das es die Aliases kopiert, etwas reinschreibt und sie dann wieder hochlädt.
Problem bei der ganzen Geschichte ist WAS er in die Datei schreibt. Er schreibt nämlich : [sudo] password for kevin: mein passtwort.
Wo nimmt er denn das her, ich habe doch etwas ganz anderes festgelegt was in die Datei geschrieben werden soll?

PythonCode:

Code: Alles auswählen

 aliasesFile = open("aliases", "r")                                      # open the aliases file which was safed in the "get_aliases" Shellscript with read access

        aliasesFileContents = aliasesFile.read().splitlines()                   # Read file into array, line by line

        aliasesFile.close()

        lines = []
        currentLine = 0                                                         # The current line is the first line in the script

        for line in aliasesFileContents:
          #  line = line.strip()
          #  if not line:
           #     pass
           # elif ':' not in line:
            #    print "Wrong line format, ':' missing in '%s'"%line
           # else:

            group, users = line.split(":")                                      # Read group data into group and user data into users

            users = users.split(", ")                                           # split the users data into every user data

            if userform.GetInput("Username") in users:                          # If user is in group
                users.remove(username.GetInput("Username"))                     # Remove user from user data

            users = ", ".join(users)                                            # Write users line again

            lines.append(group + ": " + users)                                  # Overwrite current line

            currentLine = currentLine + 1

        lines = "\n".join(lines)

        outFile = open("aliases", "w")                                          # Overwrite file
        outFile.write(lines)
        outFile.close()

BashCode:

Code: Alles auswählen

elif [ "$OPTION" = "add_cyrus_user" ]; then
	if [ "$7" = "y" ]; then
		sshpass -p "$PASSWORD" ssh -tt -oStrictHostKeyChecking=no \
			$USERNAME@$HOST \
			"
			echo -e \"$UPASSWORD\ncm user.$UUSERNAME\nsam kontakt $UUSERNAME lrswipc\nsam seminar $UUSERNAME lrswipc\nexit\" | cyradm --user cyrus localhost  &&
			sudo sed  -i -r \"s/^($UGROUPS):(.*)/\1:\2, $UUSERNAME/g\" /etc/aliases && sudo newaliases &&
			sudo mkdir /home/$USERNAME &&
			sudo touch /home/$USERNAME/aliases
			" && exit 0


	else
		sshpass -p "$PASSWORD" ssh -tt -oStrictHostKeyChecking=no \
			$USERNAME@$HOST \
			"
			echo -e \"$UPASSWORD\ncm user.$UUSERNAME\nexit\" | cyradm --user cyrus localhost
			" && exit 0
	fi
elif [ "$OPTION" = "get_aliases" ]; then
	printf "Fetching file from remote host.\n" &&
	sshpass -p "$PASSWORD" ssh -tt -oStrictHostKeyChecking=no \
		$USERNAME@$HOST \
		"
		sudo cat /etc/aliases
		" | tee aliases &&
		printf "Success!\n" && exit 0
elif [ "$OPTION" = "push_aliases" ]; then
	sshpass -p "$PASSWORD" scp aliases $USERNAME@$HOST:/home/$USERNAME &&
	sshpass -p "$PASSWORD" ssh -tt -oStrictHostKeyChecking=no \
			$USERNAME@$HOST \
			"
			echo \"$UPASSWORD\" | sudo cp aliases /etc/aliases
			" &&
	printf "Copied file.\n" && exit 0

elif [ "$OPTION" = "delete_cyrus_user" ]; then
	#echo $UUSERNAME
 	sshpass -p "$PASSWORD" ssh  -tt -oStrictHostKeyChecking=no \
 		$USERNAME@$HOST \
 		"
 		echo -e \"lm\nsam user.$UUSERNAME cyrus c\ndm user.$UUSERNAME\nexit\" | cyradm --user cyrus localhost
		"
	exit $?
fi
Sry euch so auf die Nerven zu gehen und schonmal danke für eure Hilfe

Edit:
Es wird übrigens Version 3 benutz, dass ist wahrscheinlich auch der Grund wieso der Code oben von Sirius3 einen Syntaxfehler hervorgerufen hat.

MfG
Twinhand

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Montag 15. April 2013, 08:25
von Twinhand
Hallo zusammen, mithilfe eines Kollegen habe ich es inzwischen geschafft die Aliases Datei wie gewollt umschreiben zu lassen. Das Problem ist nur das Kommentare jetzt vollkommen ausgelassen werden. Wisst ihr wie ich dafür sorgen kann, dass die Kommentare unverändert an den Platz in der Datei geschrieben werden wo sie vorher waren? DIe Lösungen die ich mir selbst zusammengereihmt habe, haben nicht so super funktioniert.

Code: Alles auswählen

        aliasesFile = open("aliases", "r")                                      # open the aliases file which was safed in the "get_aliases" Shellscript with read access

        aliasesFileContents = aliasesFile.read().splitlines()                   # Read file into array, line by line

        aliasesFile.close()

        lines = []


                                                                                # TODO If Line is not beginning with # then take the whole block
        for line in aliasesFileContents:
            if re.search('^\[sudo\].*:', line) is not None:                     # Fix for '[sudo] enter password for user:' appearing in the aliases file
                line = line.split(":")[1:]                                      # Get everything behind the first :
                line[0] = line[0].replace(" ", "")                              # Delete leading space

                line = ":".join(line)                                           # Reformat line to 'GROUP: USERS'

            if len(line.split(":")) is not 2:                                   # Skip if line is not formated 'GROUP: USERS'
                continue

            group, users = line.split(":")                                      # Read group data into group and user data into users

            if group is None or users is None:                                  # Skip if no group is in current line
                continue

            if group in userform.GetInput("Groups").split(", "):
                users = users + ", " + userform.GetInput("Username")

            lines.append(group + ": " + users)                                  # Overwrite current line

        lines = "\n".join(lines)

        outFile = open("aliases", "w")                                          # Overwrite file
        outFile.write(lines)
        outFile.close()

Danke schonmal im vorraus.

MfG
Twinhand

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Montag 15. April 2013, 09:36
von BlackJack
@Twinhand: Das ist einer der Gründe warum ich ``continue`` nicht mag. Die Behandlung von Kommentarzeilen, beziehungsweise von Zeilen die nicht einer Benutzerzeile entsprechen *da* jetzt noch rein zu basteln, macht den Codeverlauf wahrscheinlich *noch* komplizierter und undurchsichtiger.

Wenn Du sowieso schon einen regulären Ausdruck verwendest um die passenden Zeilen zu finden, dann würde ich den gleich benutzen um die Werte vor und nach dem Doppelpunkt zu extrahieren. Das macht einiges einfacher. Du hast dann in *einem* Schritt die Information ob Du die Zeile verarbeiten musst oder nicht, und auch gleich die beiden relevanten Teilstücke dieser Zeile wenn sie denn verarbeitet werden muss. Und wenn das Muster nicht zutrifft, kannst Du die Zeile einfach unverändert schreiben. Es sei denn Du willst tatsächlich noch andere Sachen aus der Datei heraus filtern.

Statt `re.search()` und einem regulären Ausdruck der mit '^' anfängt könnte man auch `re.match()` nehmen und '^' weg lassen. Explizit auf ``is None`` muss man das Ergebnis nicht testen, denn `re.search()` und auch `re.match()` geben entweder `None` zurück, was in einem boole'schen Kontext „falsch” ist, oder ein `Match`-Objekt welches in einem boole'schen Kontext immer „wahr” ist.

Der Kommentar ``# Delete leading space`` ist falsch — die `replace()`-Methode ersetzt *alle* vorkommen und nicht nur das erste. Für das beseitigen von „whitespace” (oder anderen Zeichen) am Anfang und/oder Ende gibt es die Methoden `lstrip()`, `rstrip()`, und `strip()` auf Zeichenketten.

Die ganze Verarbeitung der Zeile ist umständlich und auch nicht robust. Die Zeile wird an ':' zerlegt, dann wieder mit ':' zusammengesetzt, um dann *wieder* an ':' zerlegt zu werden. WTF‽

Dann sind dort zwei Fehler enthalten: Zahlen vergleicht man mit ``==`` oder ``!=`` aber nicht mit ``is`` oder ``is not``. Das funktioniert hier nur zufällig ist aber keinesfalls garantiert. Der andere Fehler ist das ``if group is None or users is None:``. Diese Bedingung ist Unsinn, denn in der Zeile davor werden den beiden Namen auf *jeden* Fall Zeichenketten zugewiesen, die können dort also *niemals* den Wert `None` haben.

Es wird bei dem Programm wahrscheinlich keine Probleme mit der Laufzeit geben, aber den regulären Ausdruck könnte man vor der Schleife mit `re.compile()` vorübersetzen und es wäre auch effizienter die Werte aus `userform` vor der Schleife zu ermitteln. Insbesondere den 'Groups'-Wert müsste man ja nicht ständig neu aufteilen. Wobei Du da ziemlich mutig bist, falls das tatsächlich eine Benutzereingabe sein soll. Denn das die Benutzer immer ganz brav ein Komma gefolgt von einem Leerzeichen eingeben ist eine gewagte Annahme. ;-) Wenn man das `userform` aus der Verarbeitung heraus hält, dann könnte man sie auch in eine eigene Funktion auslagern die leichter wiederverwendbar ist.

Da es sich offenbar um Systemadministration handelt, wäre es vielleicht auch nicht schlecht sich um Datenverlust Gedanken zu machen. Wenn beim Schreiben der Datei etwas passiert, dann sind die alten Daten weg. Mal angenommen in den Eingabedaten kommt ein Bytewert ausserhalb von ASCII vor, dann funktioniert das Einlesen nicht. Daraufhin änderst Du das Einlesen in dem Du eine Kodierung bei `open()` angibst. Vergisst das aber auch beim Schreiben zu tun, dass heisst das `open()` funktioniert noch, und löscht dadurch den alten Inhalt, aber das `write()` schlägt dann wegen eines Kodierungsfehlers fehl — das Programm ist beendet, die Daten sind weg, eine leere ``aliases``-Datei bleibt zurück. :-( Bei solchen wichtigen Sachen schreibt man die veränderten Daten üblicherweise erst in eine temporäre Datei und erst wenn diese erfolgreich geschrieben wurde, wird sie zu der tatsächlichen Datei umbenannt. So hat man immer noch die Originaldatei wenn irgend etwas Unverhergesehens passiert.

Im Zusammenhang mit Dateien solltest Du Dir auch mal die ``with``-Anweisung anschauen.

Die Formatierung der Kommentare ist furchtbar. Zeilen sollten höchstens 80 Zeichen lang sein. Damit verbieten sich Kommentare am Ende von Code-Zeilen, ausser sie sind wirklich sehr kurz. Wenn ich den Quelltext hier mit meiner üblichen Browserbreite anschaue, dann besteht fast jede zweite Zeile aus dem Ende des Kommentars aus der vorherigen Quelltextzeile. Weder den Quelltext noch die Kommentare kann man auf diese Weise leicht und flüssig lesen. Das ist anstrengend. Normalerweise schreibt man einen Kommentar *vor* einen Abschnitt von Quelltextzeilen der beschreibt *warum* der Code in diesen Zeilen etwas macht. *Was* er macht, sollte man aus dem Code selbst und passend gewählten Namen erkennen können. Dafür sollte man keine Kommentare benötigen.

Um eine Textdatei zeilenweise in eine Liste zu überführen kann man übrigens einfach die `list()`-Funktion mit dem Dateiobjekt aufrufen. Denn Datei-Objekte sind iterierbar und liefern dabei die einzelnen Zeilen als Elemente. Dabei bleiben die Zeilenenden-Zeichen erhalten, was aber vielleicht gar nicht so schlecht ist, denn soweit ich das sehe wird bei Dir die neu geschriebene Datei nicht mit einem Zeilenendezeichen abgeschlossen! Das ist keine gute Idee, denn es gibt *einige* Werkzeuge die damit nicht klar kommen, weil sie erwarten, dass dieses Zeichen tatsächlich am Ende von *jeder* Zeile steht. Zum Beispiel ist es nicht unüblich in Shell-Skripten mit ``echo 'something' >> test.txt`` eine Zeile hinzuzufügen. Oder mit ``cat file_one.txt file_two.txt > result.txt`` den Inhalt von zwei Dateien zu verbinden.

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Montag 15. April 2013, 11:44
von Twinhand
@BlackJack. Hallo BlackJack, danke für die schnelle Antwort. Ich werde diese Dinge gleich mal ausprobieren. Die Sache ist folgende, der Code ist nicht von mir geschrieben, jedenfalls nicht hauptsächlich, ich soll ihn nur Anpassen. Da ich mich nicht mit Python/Bash auskenne , verwende ich die Befehle die bereits im Code stehen und passe sie dem entsprechend an. Das könnte der Grund sein wieso das ganze sehr unkonventionel aussieht. Zu der Sache mit der Verbindung von 2 Dateien durch cat. Das Skript soll per Remotezugriff auf den Server zugreifen und dort die Aliases Datei verändern (also dieser Abschnitt soll das tun). Und das ist laut meinem Mitazubi ( der übrigens das Skript geschrieben hat) so möglich und wir wussten keine andere Möglichkeit wie es sonst laufen sollte.
Aus der Datei sollen insgesammt 3 "Werte" geholt werden, die Gruppe die Namen der Nutzer und die Kommentare, zusätzlich werden die Neuen Nutzer in die passenden Gruppen eingetragen ( Diese werden vom Skript abgefragt.)

Wie dem auch sei, ich werde versuchen deine Vorschläge umzusetzen.

MfG
Twinhand

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Montag 15. April 2013, 14:05
von Twinhand
@ BlackJack, könntest du mir auch zeigen wie die Syntax wäre um die Datei mit regulären Ausdrücken komplett auszulesen und dann zu verarbeiten, bzw, welche Möglichkeiten gibt es das zu realisieren mit möglichst wenig Änderungen am Code?

MfG
Twinhand

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Montag 15. April 2013, 15:28
von BlackJack
@Twinhand: Nicht die ganze Datei sondern die einzelnen Zeilen. Wobei ich gerade über dieses [sudo] stolpere: Das ist doch wohl ein Fehler der an anderer Stelle behoben werden sollte, denn diese Zeilen sollten sich doch eigentlich gar nicht in der Datei befinden‽ Und Deinen „Fix” verstehe ich nicht. Folgt denn in der selben Zeile noch eine reguläre Zeile hinter dem '[sudo] enter password for user:'?

Das Format einer ``aliases``-Datei ist auch etwas komplexer als das bisherige Skript verarbeiten kann. Es wird zum Beispiel zwischen (physischen) Zeilen und logischen Zeilen unterschieden. Wenn Dein Skript davon abweicht, solltest Du das dokumentieren und eventuell sogar zumindest auf logische Zeilen prüfen und mit einem Fehler abbrechen wenn so etwas vorkommt.

Ungetestet:

Code: Alles auswählen

    aliases_filename = 'aliases'
    names = set(n.strip() for n in userform.GetInput('Groups').split(','))
    new_value = userform.GetInput('Username').strip()

    with open(aliases_filename, 'r') as lines:
        result = list()
        for i, line in enumerate(lines, 1):
            if not is_comment_or_empty(line):
                if line[0].isspace():
                    raise ValueError('can not cope with logical lines.  :-(')
                try: 
                    name = line[:line.index(':')].strip()
                except ValueError:
                    # 
                    # Line does not contain a ':' and can not be a comment,
                    # logical or an empty line at this point, so...
                    # 
                    raise ValueError(
                        'line {0} does not contain an alias definition: {0!r}'
                            .format(i, line)
                    )
                else:
                    if name in names:
                        line = '{0}, {1}\n'.format(line.rstrip(), new_value)
            result.append(line)

    with open(aliases_filename, 'w') as aliases_file:
        aliases_file.writelines(result)
Mit:

Code: Alles auswählen

def is_comment_or_empty(line):
    line = line.strip()
    return not line or line.startswith('#')

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Dienstag 16. April 2013, 13:53
von Twinhand
@blackjack Leider hat deine Lösung bei uns nicht funktioniert, nicht das Fehler ausgeworfen wurden oder sonstiges, er hat aber leider aus welchem Grund auch immer nich die Inhalte in die Aliases Datei geschrieben die wir wollten, die Lösung auf die wir gekommen sind ( die vielleicht nicht gerade optimal ist, aber funktioniert) ist folgende:

Code: Alles auswählen

 aliasesFile = open("aliases", "r")                                      # open the aliases file which was safed in the "get_aliases" Shellscript with read access

        aliasesFileContents = aliasesFile.read().splitlines()                   # Read file into array, line by line

        aliasesFile.close()

        lines = []

        for line in aliasesFileContents:
            line = line.strip()                                                 # Delete leading space

            if not line.strip().startswith("#") and not line.startswith(" "):
                if re.search('^\[sudo\].*:', line) is not None:                 # Fix for '[sudo] enter password for user:' appearing in the aliases file
                    line = line.split(":")[1:]                                  # Get everything behind the first :
                    line = ":".join(line)                                       # Reformat line to 'GROUP: USERS'

                if len(line.split(":")) is not 2:                               # Skip if line is not formated 'GROUP: USERS'
                    continue

                group, users = line.split(":")                                  # Read group data into group and user data into users

                if group in userform.GetInput("Groups").split(", "):
                    users = users + ", " + userform.GetInput("Username")

                lines.append(group + ": " + users)
            else:
                if not re.search('^\[sudo\].*:', line):
                   lines.append(line)

        lines = "\n".join(lines)

        outFile = open("aliases", "w")                                          # Overwrite file
        outFile.write(lines)
        outFile.close()

              

Was mich zur nächsten Geschichte bringt, dem Löschen. Das Skript soll auch besagter Nutzer aus der Datei löschen können, ich habe mir gedacht das ich es nach dem Vorbild der "add-Funktion" versuche.
Das sehe dann umefähr so aus:

Code: Alles auswählen

    
        if userStatus is not 0:                                                 # If user has not been deleted
            dialog = library.gui.Dialog(title="MAIS-Tools - User Management - Remote - Delete User")
            dialog.SetText("Failed to delete user \""+username+"\". Try again?")
            dialog.AddOption("y", "Yes", lambda:self.DeleteUser())
            dialog.AddOption("n", "No", lambda:self.Menu())
            dialog.Show()
            dialog.GetInput()



        aliasesFile = open("aliases","r")

        aliasesFileContents =aliasesFile.read().splitlines()

        aliasesFile.close()

        lines = []

        for line in aliasesFileContents:
            line = line.strip()
            if not line.strip().startswith("#") and not line.startswith(" "):
                if re.search('^\[sudo\]:',line) is not None:
                    line = line.split(":")[1:]
                    line =":".join(line)

                if len(line.split(":")) is not 2:                               # Skip if line is not formated 'GROUP: USERS'
                    continue

                group, users =line.split(":")

                if users in userform.GetInput("Username"):
                    line=line.replace("Username", "")
                else:
                    if not re.search('^\[sudo\].*:', line):
                        lines.append(line)

        lines = "\n".join(lines)

        outFile = open("aliases", "w")                                          # Overwrite file
        outFile.write(lines)
        outFile.close()

Leider löscht dieser Code die die Kommentare aus der Datei, aber nicht das was er eigentlich sollte, vielleicht hänge ich gerade schon zu lange dran um den wahrscheinlich offensichtlichen Fehler selbst zu finden, wenn ihr seht was nicht stimmt wäre ein Post nett.^^

Ich danke schonmal im vorraus


MfG
Twinhand

Re: Das Aktualisieren einer Aliases Datei mit Hilfe von Pyth

Verfasst: Donnerstag 18. April 2013, 09:20
von Twinhand
Hallo zusammen,

das Skript läuft inzwischen so wie es soll, der Code dafür sieht wie folgt aus:

Code: Alles auswählen

aliasesFile = open("aliases","r")                                       # opens aliases file

        aliasesFileContents = aliasesFile.read().splitlines()                   # write content of aliases in array

        aliasesFile.close()                                                     # close aliases

        lines = []

        for line in aliasesFileContents:
            if not line.strip().startswith("#") and not line.startswith(" "):   # check if the line doesnt start with "#" or " "
                line = line.replace(" ", "")                                    # Replaces unnecessary spaces

                if re.search('^\[sudo\].*:', line) is not None:                 # Fix for '[sudo] enter password for user:' appearing in the aliases file
                    line = line.split(":")[1:]                                  # Get everything behind the first :
                    line = ":".join(line)                                       # Reformat line to 'GROUP: USERS'

                if len(line.split(":")) is not 2:                               # Skip if line is not formated 'GROUP: USERS'
                    continue

                group, users = line.split(":")                                  # Split the line in Group : users

                users = users.split(",")                                        # Split users with a ,

                if username in users:                                           # searches for username in users
                    users.remove(username)                                      # removes username from users

                users = ", ".join(users)                                        # join the lines together with a ,

                lines.append(group + ": " + users)                              # write groups and users in the line
            else:                                                               # happens if line starts with "#" or " "
                if not re.search('^\[sudo\].*:', line):                         # Fix for '[sudo] enter password for user:' appearing in the aliases file
                    lines.append(line)                                          # write characters in line

        lines = "\n".join(lines)                                                # write the lines

        outFile = open("aliases", "w")                                          # Opens file with write access
        outFile.write(lines)                                                    # write lines in the file
        outFile.close()             

Ich hoffe das dieser Code auch anderen Leuten hilft die womöglich ähnliche Probleme haben ( auch wenn er nicht perfekt ist, er läuft^^) .

Ich danke euch allen für eure Hilfe.:)

MfG
Twinhand

closed