Seite 1 von 2
Befehle aus txt Datei lesen
Verfasst: Dienstag 6. April 2010, 23:31
von Baconman
Hoy
Ich schreibe im Moment einen IRC Bot. Klappt auch alles prima, nur möchte ich die "Befehele" nun ,der Übersicht halber, aus einer txt Datei auslesen.
Die Datei ist folgender Maßen aufgebaut:
Code: Alles auswählen
Text aus dem IRC Channel === Das sagt der Bot
zweiter Text aus dem Channel === Das sagt der Bot auf "zweiter Text aus dem Channel"
...
So die erste Zeile auslesen klappt prima. Sobald ich aber den Text der zweiten Zeile in den Channel schreibe scheint sich der Bot aufzuhängen. Es kommt zwar keine Fehlermeldung aber er protokolliert die Aktivität im Channel nicht mehr weiter.
Hier der Code mit dem ich versuche die Befehle aus der Text Datei zu lesen:
Code: Alles auswählen
if data[1] =='privmsg':
weiter = 'true'
while weiter == 'true':
i = 0
datei = open('Befehle.txt', 'r')
zeile = datei.readlines()
teiler = zeile[i].split('===')
ereignis = teiler[0].split(' ')
j = 0
while j < len(ereignis):
if ereignis[j] in text:
j = j + 1
if j == len(ereignis):
irc.send('PRIVMSG ' + channel + ' ' + teiler[1])
i = 0
weiter = 'false'
else:
i = i + 1
Hat einer von euch eine Idee wie ich das vielleicht lösen könnte?(Möglichst elegant und nicht so wie ich

)
Verfasst: Dienstag 6. April 2010, 23:59
von BlackJack
@Baconman: Mach Dir einfach mal Gedanken darüber was Du denkst an was die Namen in dem Skript zu jedem Zeitpunkt gebunden sind. Und dann überprüfe Deine Vermutungen. Zum Beispiel mit ``print``. Gute Kandidaten wären zum Beispiel `i` und `zeile`.
Es gibt für Wahrheitswerte extra einen Typ in Python.
Verfasst: Mittwoch 7. April 2010, 11:41
von sma
Die innere while-Schleife endet nicht, wenn das erste Wort aus `ereignis` nicht in `text` vorkommt. Damit hängt das Programm.
Ich würde übrigens empfehlen, den Text nur einmal einzulesen und dann in einem dict (o.ä.) zu halten. Auch ist mir nicht klar, warum nicht einfach dies reichen sollte:
Code: Alles auswählen
replies = dict(line.split(" === ") for line in open("befehle.txt"))
def wo_kommt_wohl_in_deinem_beispiel_text_her(irc, reply, text):
reply = replies.get(text, "what?!")
irc.send('PRIVMSG %s %s' % (channel, reply))
Stefan
Verfasst: Mittwoch 7. April 2010, 14:57
von Baconman
Von dem immer wieder neu auslesen das Textdokumentes erhoffe ich mir "Live Änderungen" durchführen zu können.
Dein vorgeschlagenes Beispiel geht deshalb nicht, weil in der Text Datei auch der Auslöser stehen soll.
Ich werde eure beiden Hinweise mal testen gehen

Verfasst: Donnerstag 8. April 2010, 08:29
von /me
Baconman hat geschrieben:Von dem immer wieder neu auslesen das Textdokumentes erhoffe ich mir "Live Änderungen" durchführen zu können.
Aber doch wohl nicht während eine einzige Message verarbeitet wird. Ich glaube nicht, dass du im Bereich von wenigen Millisekunden die Datei sinnvoll editieren kannst.
Verfasst: Donnerstag 8. April 2010, 12:54
von Baconman
Ich kann doch einfach die txt Datei öffnen , was rein schreiben, speichern und dann wird der neue Befehl beim nächsten mal beachtet. Oder etwa nicht?
Soweit ich das überblicken kann, bin ich übe rings zu blöd mein oben beschriebenes Problem selbst zu lösen

Verfasst: Donnerstag 8. April 2010, 13:23
von /me
Baconman hat geschrieben:Ich kann doch einfach die txt Datei öffnen , was rein schreiben, speichern und dann wird der neue Befehl beim nächsten mal beachtet. Oder etwa nicht?
Soweit ich das überblicken kann, bin ich übe rings zu blöd mein oben beschriebenes Problem selbst zu lösen

Dein Code sieht deutlich komplizierter aus als deine Beschreibung es nahelegt.
Beschreib doch mal in Worten möglichst deutlich, was passieren soll. Ich gehe im Moment von folgendem aus:
In der Textdatei befinden sich einzelne Zeilen die als Trenner den String "===" enthalten. Der Teil hinter dem Trenner soll das Ergebnis sein. Der Teil vor dem Trenner ... ja, und hier kommt jetzt die Frage:
- * soll genau der Eingabe entsprechen?
* soll ein Teil der Eingabe sein?
* ist eine Liste von Worten die irgendwie in der Eingabe vorkommen sollen?
Verfasst: Donnerstag 8. April 2010, 13:53
von Baconman
Du hast es soweit schon richtig verstanden

Der Teil vor dem Trenner ist eine Aufreihung von Worten die irgendwo in der Eingabe vorkommen sollen.
Jede Zeile hat einen "Auslöser" und eine "Reaktion":
"Auslöser" === "Reaktion"
Verfasst: Donnerstag 8. April 2010, 14:37
von /me
Baconman hat geschrieben:Du hast es soweit schon richtig verstanden

Der Teil vor dem Trenner ist eine Aufreihung von Worten die irgendwo in der Eingabe vorkommen sollen.
Jede Zeile hat einen "Auslöser" und eine "Reaktion":
"Auslöser" === "Reaktion"
So ganz spontan:
Code: Alles auswählen
filedata = ["welcome === my humble greetings to you",
"hard burn === like a leaf in the wind"]
input_data = "burn it hard, Wash!"
actions = []
for line in filedata:
parts = line.split("===")
actions.append((parts[0].split(), parts[1]))
for action in actions:
if all([False for word in action[0] if input_data.find(word) < 0]):
print(action[1])
Jetzt sollten beim Aufbau der Datenstruktur nur noch die Leerzeichen um die Worte bzw. Sätze entfernt werden und eine Umwandlung in Kleinbuchstaben wäre wahrscheinlich auch gut.
Verfasst: Donnerstag 8. April 2010, 14:40
von .robert
Hi,
bin mir zwar nicht sicher ob ich es richtig verstanden habe, aber müssen dass unbedingt die "===" als Trenner sein?
Du könntest schon fertige Formate wie ini oder csv oder (für Masochisten) xml. Für die gibt es schon fertige Parser.
Verfasst: Donnerstag 8. April 2010, 14:47
von /me
.robert hat geschrieben:bin mir zwar nicht sicher ob ich es richtig verstanden habe, aber müssen dass unbedingt die "===" als Trenner sein?
Der Trenner ist wohl weniger das Problem hier.
Verfasst: Donnerstag 8. April 2010, 14:56
von BlackJack
@/me: Zeile 12 ist ein schlechter Scherz oder? Gibt's einen Weg das *noch* verwirrender auszudrücken?

Verfasst: Donnerstag 8. April 2010, 15:01
von /me
BlackJack hat geschrieben:@/me: Zeile 12 ist ein schlechter Scherz oder? Gibt's einen Weg das *noch* verwirrender auszudrücken?

Spontan schien mir die Lösung mit all() eine gute Idee zu sein. Dann fiel mir auf, dass all() bei einer leeren Liste auch True zurückgibt und das passte dann wieder nicht und so wurde die Lösung nicht mehr ganz so elegant.
Wie wäre es denn schöner?
Verfasst: Donnerstag 8. April 2010, 15:05
von BlackJack
Schöner wäre es nicht ``in`` und `find()` zu mischen, die unnötigen eckigen Klammern wegzulassen und gleich die richtige Funktion zu verwenden, statt `any()` mit diversen "Negationen" mit `all()` nachbasteln zu wollen:
Code: Alles auswählen
for words, response in actions:
if any(word in input_data for word in words):
print response
Verfasst: Donnerstag 8. April 2010, 15:08
von Baconman
Ich gucke mir eure Vorschläge mal an
Eine Umwandlung des gedammten Inputs in klein Buchstaben habe ich bereits integriert.
BlackJack: Kannst du vielleicht kurz erklären was "actions" ist?
Verfasst: Donnerstag 8. April 2010, 15:14
von /me
BlackJack hat geschrieben:Schöner wäre es nicht ``in`` und `find()` zu mischen, die unnötigen eckigen Klammern wegzulassen und gleich die richtige Funktion zu verwenden, statt `any()` mit diversen "Negationen" mit `all()` nachbasteln zu wollen:
Sehr schön, allerdings ist any() IMHO falsch und nicht das was der OP wollte. Es sollen ja eben alle Wörter in der Eingabe vorkommen.
Verfasst: Donnerstag 8. April 2010, 15:53
von BlackJack
@Baconman: `actions` ist das selbe wie in /me's Quelltext eine Liste mit Tupeln aus Wörtern und einer dazu passenden Anwort.
@/me: Aber dann braucht man in meinem Schnipsel doch nur `any()` durch `all()` ersetzen. Dann verstehe ich noch weniger warum Deins so kompliziert geschrieben ist!?
Verfasst: Donnerstag 8. April 2010, 21:28
von Baconman
Hab jetzt versucht den Schnipsel einzubinden!
Leider ohne Erfolg... es wäre nett wenn mir jemand noch erklären könnte was ich falsch mache.
Code: Alles auswählen
if data[1] =='privmsg':
filedata = open('Befehle.txt', 'r')
actions = []
for line in filedata:
parts = line.split('===')
actions.append((parts[0].split(), parts[1]))
words = parts[0]
response = parts[1]
for words, response in actions:
if all(word in data for word in words):
irc.send('PRIVMSG ' + channel + ' :' + response)
Verfasst: Donnerstag 8. April 2010, 21:39
von BlackJack
@Baconman: Also mindestens das ``word in data`` wird wohl so nicht funktionieren. Überlege Dir mal an was `data` gebunden ist, und warum da wahrscheinlich nie `word` drin vorkommen wird.
Verfasst: Freitag 9. April 2010, 08:09
von /me
BlackJack hat geschrieben:@/me: Aber dann braucht man in meinem Schnipsel doch nur `any()` durch `all()` ersetzen. Dann verstehe ich noch weniger warum Deins so kompliziert geschrieben ist!?
Ganz einfach. Ich war irgendwie auf eine Liste fixiert und habe deshalb einen verkorksten Ansatz gewählt.