Liste nach Inhalt abfragen

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
lordzwieback
User
Beiträge: 55
Registriert: Montag 2. März 2015, 14:35
Kontaktdaten:

Hallo,

ich habe ein Dictionary (PC-Nummer: Benutzername) erstellt und gleichzeitig lasse ich den Befehl "query user /server:PC-Nummer" laufen. Die Ausgabe des Befehls lasse ich mir in eine Variable schreiben. Diese Variable splitte ich dann auf, sodass eine Liste erzeugt wird. Jedes Wort ist ein Listenobjekt.

Danach möchte ich abfragen, ob der Wert eines Keys aus dem Dictionary in der Liste erscheint. Das Ganze sieht bei mir momentan (Test) so aus:

Code: Alles auswählen

import subprocess

user = {"PC-Nummer": "user"}
response = subprocess.Popen([r"C:\Windows\Sysnative\query.exe","user", "/server:PC-Nummer"], stdout= subprocess.PIPE).communicate()[0]

test = response.split()
print(test)
for key in user:
    if user.get(key) in test:
        print("JUHU")
    else:
        print("MÄH")
Das gleiche noch mit der Abfrage auf jedes Wort einzeln:

Code: Alles auswählen

import subprocess

user = {"PC-Nummer": "user"}
response = subprocess.Popen([r"C:\Windows\Sysnative\query.exe","user", "/server:PC-Nummer"], stdout= subprocess.PIPE).communicate()[0]

test = response.split()
print(test)
for key in user:
	for word in test:
    		if user.get(key) in test:
        	print("JUHU")
    	else:
        	print("MÄH")
Folgendes Problem: Der Username steht ganz eindeutig in der Liste als sechstes Element drin. Ich sehe das beim "printen" der Liste. Ausgabe ist immer "MÄH" :D

Die einzelnen Elemente der Liste sind so formatiert: [b'Hallo', b'ich', b'weiß', b'nicht', b'weiter']. Ist das normal ? Haben die Hochkommata und das vorangestellte b eine besondere Bedeutung ? Konnte dazu in meinen Quellen nichts finden. Wird der Name evtl wegen der Formatierung nicht erkannt ?

Schonmal danke für eure Hilfe. :)

Grüße

EDIT:
Habe mal noch eine kleine von Hand erstellte Liste nach dem gleichen Prinzip wie oben durchsucht, da funktioniert alles. Muss ich beim Durchsuchen von gesplitteten Strings etwas beachten ?
lordzwieback
User
Beiträge: 55
Registriert: Montag 2. März 2015, 14:35
Kontaktdaten:

Habe es glaube ich rausgefunden. Das "b" ist ein Präfix, welches bedeutet, dass der Wert im Binärformat ursprünglich vorliegt.

Um den Wert richtig abfragen zu können, muss er umcodiert werden.

Code: Alles auswählen

for word in test:
	word = str(word, encoding="utf-8")	
Hat bei mir geholfen.

Weitere Frage: Normalerweise sollte ich doch über den Index auf ein bestimmtes Wort nun zugreifen können. Wenn ich das versuche, bekomme ich folgende Fehlermeldung:

IndexError: string index out of range

In der Liste sind immer 13 (Index: 0-12) Elemente vorhanden. Weiß da jemand weiter ?

Gruß
sebastian0202
User
Beiträge: 168
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Python 3.x makes a clear distinction between the types:

str = '...' literals = a sequence of Unicode characters (UTF-16 or UTF-32, depending on how Python was compiled)
bytes = b'...' literals = a sequence of octets (integers between 0 and 255)
Das 'b' vor den Wörtern hat also tatsächlich was zu bedeuten.
Demnach sind in Python3 'ich_bin_text' und b'ich_bin_text' nicht gleich.



edit:
Möchtest du auf das Element einer Liste zugreifen?
Deine Fehlermeldung sagt nämlich was anderes.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@lordzwieback: das dekodieren solltest Du schon früher machen, und zwar nicht mit der str-Funktion sondern mit der decode-Methode auf byte-Objekten:

Code: Alles auswählen

test = response.decode('utf-8').split()
wobei Du Dir auch sicher sein solltest, dass query.exe die Ausgabe auch utf8-codiert. Standard ist bei Windows-Konsolenprogrammen immer noch Latin-1. Wenn Du sowieso nur die Werte eines Dictionaries haben willst, gibt es die items-Methode. Für das Testen auf Vorhandensein bietet es sich an, statt einer Liste ein Set zu benutzen.
lordzwieback
User
Beiträge: 55
Registriert: Montag 2. März 2015, 14:35
Kontaktdaten:

Sirius3 hat geschrieben:@lordzwieback: das dekodieren solltest Du schon früher machen, und zwar nicht mit der str-Funktion sondern mit der decode-Methode auf byte-Objekten:

Code: Alles auswählen

test = response.decode('utf-8').split()
wobei Du Dir auch sicher sein solltest, dass query.exe die Ausgabe auch utf8-codiert. Standard ist bei Windows-Konsolenprogrammen immer noch Latin-1. Wenn Du sowieso nur die Werte eines Dictionaries haben willst, gibt es die items-Methode. Für das Testen auf Vorhandensein bietet es sich an, statt einer Liste ein Set zu benutzen.
Vielen Dank für den Tipp, werde es gleich mal testen und Bescheid geben, wies ausschaut.
lordzwieback
User
Beiträge: 55
Registriert: Montag 2. März 2015, 14:35
Kontaktdaten:

sebastian0202 hat geschrieben:
Möchtest du auf das Element einer Liste zugreifen?
Deine Fehlermeldung sagt nämlich was anderes.
Ich habe meinen Fehler gefunden. Ich wollte nur das eine Listenelement untersuchen mittels word[6] (Username). Nur leider habe ich da das Wort und nicht das Element an sich angesprochen. Deshalb auch "out of range".

Danke für den Denkanstoß. Klar, kam mir die Fehlermeldung schon komisch vor, aber habe im ersten Moment nicht dran gedacht, dass ich es ander falschen Stelle stehen habe. Jetzt funktioniert es, danke.
lordzwieback
User
Beiträge: 55
Registriert: Montag 2. März 2015, 14:35
Kontaktdaten:

Nochmal die funktionierende Lösung:

Code: Alles auswählen

import subprocess

user = {"PC123": "Mustermann"}
response = subprocess.Popen([r"C:\Windows\Sysnative\query.exe","user", "/server:PC123"], stdout= subprocess.PIPE).communicate()[0]
test = response.decode("Latin-1").split()

for key in user:
    if user.get(key) in test[6]:
        print("Mustermann in Liste vorhanden")
    else:
        continue
Danke für eure Hilfe :>
BlackJack

@lordzwieback: Diese ``for``-Schleife ist merkwürdig. `key` interessiert dich doch hier überhaupt nicht, iteriere besser direkt über die Werte. Selbst wenn Du den Umweg über den Schlüssel gehst, macht `get()` keinen Sinn. Den Schlüssel gibt es ganz sicher, denn Du hast ihn ja aus dem Wörterbuch. Das nächste ist dann der ``in``-Test — sowie Du einen Nutzernamen hast, der Teil eines anderen Nutzernamens ist, bekommst Du hier falsche Treffer. Das ``else`` mit dem ``continue`` ist an der Stelle komplett sinnfrei. ``continue`` würde ich sowieso vermeiden weil das (wenn es sinnvoll eingesetzt wird) ein unbedingter Sprung an den Schleifenanfang darstellt, der sich nicht in der Einrückung ablesen lässt und somit leicht übersehen werden kann. Ausserdem macht er das Ergänzen des Schleifenkörpers um Aktionen die an jedem Durchlaufende durchgeführt werden sollen schwieriger, und die Anweisung verhindert, dass man den Schleifenkörper einfach in eine Funktion auslagern kann.
lordzwieback
User
Beiträge: 55
Registriert: Montag 2. März 2015, 14:35
Kontaktdaten:

BlackJack hat geschrieben:@lordzwieback: Diese ``for``-Schleife ist merkwürdig. `key` interessiert dich doch hier überhaupt nicht, iteriere besser direkt über die Werte. Selbst wenn Du den Umweg über den Schlüssel gehst, macht `get()` keinen Sinn. Den Schlüssel gibt es ganz sicher, denn Du hast ihn ja aus dem Wörterbuch. Das nächste ist dann der ``in``-Test — sowie Du einen Nutzernamen hast, der Teil eines anderen Nutzernamens ist, bekommst Du hier falsche Treffer. Das ``else`` mit dem ``continue`` ist an der Stelle komplett sinnfrei. ``continue`` würde ich sowieso vermeiden weil das (wenn es sinnvoll eingesetzt wird) ein unbedingter Sprung an den Schleifenanfang darstellt, der sich nicht in der Einrückung ablesen lässt und somit leicht übersehen werden kann. Ausserdem macht er das Ergänzen des Schleifenkörpers um Aktionen die an jedem Durchlaufende durchgeführt werden sollen schwieriger, und die Anweisung verhindert, dass man den Schleifenkörper einfach in eine Funktion auslagern kann.
Danke für die Kritik. Das mit dem "in" sehe ich ein, da wäre wohl eine direkte Abgleichsabfrage besser (==). Das mit dem continue leuchtet mir auch ein.

Aber deine Anmerkung für das for verstehe ich leider nicht :( Ich brauche den Key. Der Key ist der PC Name des jeweiligen Users. Dieser ist einzigartig und wird später im Befehl an der Stelle "/server:PC Name" verwendet. Das Codestück oben war nur dazu da, um die Funktionen zu testen, damit ich nicht im eigentlichen Programm rumwurschteln muss und am Schluss nicht mehr klar ist, wo was gestanden hat, weil ich zu viele Änderungen gemacht habe.

Falls ich etwas falsch verstanden habe, tuts mir leid. :D
BlackJack

@lordzwieback: Ich kann ja nur was zu Code sagen den ich kenne. Und in dem den Du gezeigt hast wird in der ``for``-Schleife `key` nicht wirklich gebraucht, weil man da gleich über die Werte des Wörterbuchs iterieren könnte.

Code: Alles auswählen

for value in user.values():
    if value == test[6]:
        print('Mustermann in Liste vorhanden')
Und für das was dann in der Schleife gemacht wird, bräuchte man noch nicht einmal eine Schleife, es sei denn man möchte die Ausgabe tatsächlich mehrfach haben wenn der Benutzername mehrfach in den Werten vorkommt:

Code: Alles auswählen

if test[6] in user.values():
    print('Mustermann in Liste vorhanden')
Antworten