Seite 1 von 2
Variable in Befehl einbauen
Verfasst: Mittwoch 1. Januar 2014, 15:22
von fenestro
Guten Tag
Ich programmiere gerade den "Prozessor" für meine Haussteuerung mit Python, hab allerdings ein paar kleine Probleme.
Hier mein Code:
Code: Alles auswählen
if GPIO23_in == "1":
print "erkannt dass gpio23 input"
if ( GPIO.input(16) == True ):
print "erkannt dass schalter gedruckt"
dateiname = "/var/www/settings/zuweisungen/GPIO2.txt"
a = []
with open(dateiname, 'r') as f:
for line in f:
a.append(int(line))
akt1= a[1]
akt2= a[2]
akt3= a[3]
print akt1
print akt2
print akt3
dateiname = "/var/www/settings/onoff.txt"
a = []
with open(dateiname, 'r') as f:
for line in f:
a.append(int(line))
print a[akt1]
print a[akt2]
print a[akt3]
if a[akt1] == a[akt2]:
if a[akt2] == a[akt3]:
if a[akt1] == "1":
GPIO.output(akt1, GPIO.LOW) //hier problem 1
GPIO.output(akt2, GPIO.LOW)
GPIO.output(akt3, GPIO.LOW)
print "alle ein"
time.sleep(2)
elif a[akt1] == "0":
GPIO.output(akt1, GPIO.HIGH)
GPIO.output(akt2, GPIO.HIGH)
GPIO.output(akt3, GPIO.HIGH)
print "alle aus"
time.sleep(2)
else:
GPIO.output(akt1, GPIO.HIGH)
GPIO.output(akt2, GPIO.HIGH)
GPIO.output(akt3, GPIO.HIGH)
print "alle aus"
time.sleep(2)
else:
GPIO.output(akt1, GPIO.HIGH)
GPIO.output(akt2, GPIO.HIGH)
GPIO.output(akt3, GPIO.HIGH)
print "alle aus"
time.sleep(2)
Ich habe die Variable akt3 und möchte sie in folgenden Befehl intergrieren:
Habe es wie oben zu sehen so versucht:
und bekomme folgende Fehlermeldung rausgeschmissen:
Traceback (most recent call last):
File "fertig/processor.py", line 564, in <module>
GPIO.output(akt2, GPIO.HIGH)
ValueError: The channel sent is invalid on a Raspberry Pi
2. Wollte ich noch fragen ob es die Möglichkeit gibt in eine bestimmte Zeile einer Datei zu schreiben.
und 3. und letztens würde ich mich über Tipps freuen den Code etwas zu verkürzen.
60 Zeilen pro Pin und dass ohne Speicherung sind doch ziemlich viel ^^
Mir fehlt es wohl noch an einigen Basics, weis allerdings nicht nach was ich am besten suchen soll.
Betreibe eher Learning by doing und werde nachdem dieses "Großprojekt" abgeschlossen ist nicht mehr all zu viel mit Python machen, weshalb ich nicht unbedingt Lust hab jetzt Tagelang Basics zu pauken...
Hoffe ihr habt ein paar Tipps für mich
mfg
Fenestro
Re: Variable in Befehl einbauen
Verfasst: Mittwoch 1. Januar 2014, 16:13
von BlackJack
@fenestro: Das ist ja jetzt grundsätzlich erst einmal kein Problem eine Variable statt eines festen Wertes einzusetzen, sondern dass der Wert in der Datei offenbar falsch ist, weil es kein gültiger Wert für einen Pin ist.
Bezüglich des Verkürzens: Da wird in vielen Zweigen ja das gleiche gemacht. Eigentlich sind *alle* fast gleich. Die unterscheiden sich ja nur durch das zweite Argument bei den `output()`-Aufrufen und ein Wort im Ausgabetext. Da würde man sinnvollerweise die Bedingungen in *einem* ``if`` zusammenfassen und nicht für jede Teilbedingung ein neues ``if``/``else`` schreiben, und aufgrund der Bedingung nur die beiden Unterschiede an Namen binden und die dann danach in den 5 Zeilen verwenden die in jedem Zweig stehen, aber eigentlich nur einmal benötigt werden.
Oh, und zeig bitte Code der zum Problem passt, denn da wo Du den syntaktisch falschen Kommentar gesetzt hast, dass dort das Problem ist, haben wir eine Codezeile die niemals ausgeführt werden kann weil die Bedingung ``a[akt1] == "1"`` niemals zutreffen kann. In der Liste `a` befinden sich zu dem Zeitpunkt ganze Zahlen und es gibt keine ganze Zahl die gleich irgendeiner Zeichenkette ist.
Re: Variable in Befehl einbauen
Verfasst: Mittwoch 1. Januar 2014, 20:45
von fenestro
doch doch das klappt,
das Problem war dass es zwei verschiedene id Typen gab, die die ich für die Zeichenreihenfolge in der Datei verwendet habe und die Pin Nummern. Ich habe die selbe verwendet, hab jetzt ne Funktion geschrieben die dass konvertiert und somit ist das Problem gelöst.
Hoffe irgendjemand hat noch ne Antwort auf Frage 2 parat.
Danke für die Hilfe jedenfalls

Re: Variable in Befehl einbauen
Verfasst: Mittwoch 1. Januar 2014, 20:52
von BlackJack
@fenestro: Zu Frage 2: Nein so allgemein ist das nicht möglich.
Re: Variable in Befehl einbauen
Verfasst: Mittwoch 1. Januar 2014, 21:19
von fenestro
Das hätte ich mir fast schon gedacht...
ohne eine solche Funktion ist mein Script jedoch hinfällig.
Hast du einen Lösungsansatz für mich?
U.u. paar Funktionen die mir weiterhelfen könnten?
Re: Variable in Befehl einbauen
Verfasst: Mittwoch 1. Januar 2014, 21:35
von mutetella
@fenestro: Wie BlackJack schon sagte: "... so allgemein [...] nicht ..." Das heißt aber nicht, dass es sonderlich kompliziert wäre. Ich würde dazu die Datei Zeile für Zeile einlesen und gleich wieder Zeile für Zeile in eine neue Datei schreiben. Ist die bedingte Zeile erreicht, schreibe ich die gewünschte neue Zeile und fahre dann mit den restlichen Zeilen fort. Danach benenne ich die neue Datei mit dem Namen der eingelesenen Datei um.
mutetella
Re: Variable in Befehl einbauen
Verfasst: Mittwoch 1. Januar 2014, 21:38
von BlackJack
@fenestro: Den Pfadangaben nach scheint es sich um eine Webanwendung zu handeln — da würde ich mal eine Datenbank vorschlagen.
Re: Variable in Befehl einbauen
Verfasst: Mittwoch 1. Januar 2014, 22:16
von fenestro
ist richtig ja,
die von mir gewünschte Aufgabe war jedoch bei PHP mit Textdateien einfacher zu lösen,
außerdem finde ich es praktischer, da man viel einfacher etwas von Hand ändern kann oder bestimmt konfigurierte Dateien einspielen kann.
@BlackJack
Da fehlt mir wohl noch Theoretisches wissen dazu.

Hoffe mal das Internet spuckt irgendwas brauchbares aus...
Re: Variable in Befehl einbauen
Verfasst: Mittwoch 1. Januar 2014, 22:26
von mutetella
@fenestro: Die Methoden, die Du auf
file objects anwenden kannst, müssten Dir IMHO alles, das Du brauchst, zur Verfügung stellen.
mutetella
Re: Variable in Befehl einbauen
Verfasst: Mittwoch 1. Januar 2014, 22:30
von BlackJack
@fenestro: Was war denn bei PHP einfacher? Auch in PHP kann man im allgemeinen nicht gezielt eine Zeile in einer Textdatei überschreiben. Das hat letztendlich nichts mit der Programmiersprache zu tun, sondern wie auf modernen Dateisystemen Textdateien gespeichert sind: eine lineare Folge von Bytes.
Re: Variable in Befehl einbauen
Verfasst: Donnerstag 2. Januar 2014, 00:15
von mutetella
Hab' mal was gebastelt:
Code: Alles auswählen
def insert_line(file_, content, line_no=None, line=None):
file_.seek(0)
for idx, item in enumerate(file_):
yield item
if idx + 1 == line_no or item.strip('\n') == line:
yield '{}\n'.format(content)
Code: Alles auswählen
In [7]: cat test
1
2
4
In [8]: t = open('test', 'r')
In [9]: new_t = open('new_test', 'w')
In [10]: new_t.writelines(insert_line(t, '3', line_no=2))
In [11]: new_t.close()
In [12]: cat new_test
1
2
3
4
In [13]: mv new_test test
mv: „test“ überschreiben? j
In [14]: t = open('test', 'r')
In [15]: new_t = open('new_test', 'w')
In [16]: new_t.writelines(insert_line(t, '5', line='4')
In [17]: new_t.close()
In [18]: cat new_test
1
2
3
4
5
Natürlich müssen die Dateien noch sauber geöffnet, geschlossen und umbenannt werden, hab' ich jetzt aber keine Lust mehr...
mutetella
Re: Variable in Befehl einbauen
Verfasst: Donnerstag 2. Januar 2014, 00:59
von BlackJack
@mutetella: Warum das `seek()` am Anfang? Und das die Funktion im Grunde zwei verschiedene Dinge macht ist IMHO auch nicht schön.
`enumerate()` kann man auch einen optionalen Startwert geben. Ich fänd als API aber besser es wie beim Slicing zu machen so dass die Zahl nicht die Zeile sondern den „Zwischenraum” angibt. Dann könnte man das auch so schreiben, dass man eine Zeile vor der ersten Zeile einfügen kann.
Wobei ich die Aufgabe mit der Zeilen*nummer* wahrscheinlich mit `itertools.islice()` für den Teil vor der Zeile gelöst hätte, statt mit `enumerate()`.
Re: Variable in Befehl einbauen
Verfasst: Donnerstag 2. Januar 2014, 12:48
von mutetella
BlackJack hat geschrieben:Warum das `seek()` am Anfang? Und das die Funktion im Grunde zwei verschiedene Dinge macht ist IMHO auch nicht schön.
Das `seek()` hab' ich vergessen, war nur zum Testen, damit ich nicht jedesmal die Datei neu öffnen muss. Und dass die Funktion zwei verschiedene Optionen bedient ist nicht schön, stimmt. Nachdem ich nicht weiß, ob fenestro die Zeilennummer oder den Zeileninhalt zum Einfügen verwenden möchte, habe ich einfach mal beides berücksichtigt.
Hab's jetzt mal so aufgeteilt:
Code: Alles auswählen
def insert_before_index(file_, index, content):
content = '{}\n'.format(content)
return itertools.chain(
itertools.islice(file_, index), (content,), file_
)
def insert_before_text(file_, text, content):
content = '{}\n'.format(content)
text = '{}\n'.format(text)
file_ = list(file_)
index = file_.index(text)
return file_[:index] + [content] + file_[index:]
mutetella
Re: Variable in Befehl einbauen
Verfasst: Donnerstag 2. Januar 2014, 13:29
von Sirius3
@mutetella: warum verwendest Du für die zweite Funktion nicht auch »itertools«:
Code: Alles auswählen
def insert_before_text(file_, text, content):
content = '{}\n'.format(content)
text = '{}\n'.format(text)
return itertools.chain(
itertools.takewhile(text.__ne__, file_), (content,text), file_
)
Re: Variable in Befehl einbauen
Verfasst: Donnerstag 2. Januar 2014, 15:05
von fenestro
Vielen vielen Dank!
Ich hätte zwar nur schreiben nach Zeilennummer gebraucht aber lieber zu viel als zu wenig

Werde das gleich nach der Arbeit ausprobieren.
Mfg
Fenestro
Re: Variable in Befehl einbauen
Verfasst: Donnerstag 2. Januar 2014, 19:39
von fenestro
Irgendwas klappt da nicht ganz

Speicherung erfolgt, die Datei sieht dann aber statt
so aus:
Habs u.a. so versucht:
Code: Alles auswählen
import itertools
import os
def insert_line(file_, content, line_no=None, line=None):
for idx, item in enumerate(file_):
yield item
if idx + 1 == line_no or item.strip('\n') == line:
yield '{}\n'.format(content)
file = open('/var/www/lol.txt', 'r')
file_new = open('/var/www/lol_new.txt', 'w')
file_new.writelines(insert_line(file, '0', line_no=1))
file_new.close()
os.rename('/var/www/lol_new.txt','/var/www/lol.txt')
Re: Variable in Befehl einbauen
Verfasst: Donnerstag 2. Januar 2014, 23:18
von cofi
Nun deine Erwartung ist falsch, denn `enumerate` beginnt bei "0" und damit auch die Zeilennummern/-indizes.
Der Code hat aber tatsaechlich einen Fehler, da man nicht vor der ersten Zeile (Nummer 0) einfuegen kann, selbst wenn man die richtigen Indizes nutzt.
Ungetestet: Verschiebe Zeile 9 hinter den `if`-Block.
Re: Variable in Befehl einbauen
Verfasst: Donnerstag 2. Januar 2014, 23:32
von mutetella
Die Version, die Du da verwendest, fügt hinter die gewünschte Zeile etwas an, Du möchtest davor einfügen. Lies Dir die Beiträge, die zwischen meiner ersten und der letzten Version ausgetauscht wurden, nochmals durch!
Code: Alles auswählen
def insert_before_index(file_, index, content):
content = '{}\n'.format(content)
return itertools.chain(
itertools.islice(file_, index), (content,), file_
)
Wenn Deine Datei so
aussieht und Du vor die erste Zeile eine '0' einfügen möchtest, dann gehst Du folgendermaßen vor:
Code: Alles auswählen
def insert_line(filename, index, content):
tmp_filename = '{}.tmp'.format(filename)
with open(filename, mode='r') as orig_file:
with open(tmp_filename, mode='w') as tmp_file:
try:
tmp_file.writelines(
insert_before_index(orig_file, index, content)
)
except Exception:
os.remove(tmp_file)
raise
shutil.move(tmp_filename, filename)
Code: Alles auswählen
In [8]: cat test
1
1
1
In [9]: insert_line('test', 0, '0')
In [10]: cat test
0
1
1
1
Noch zur Erklärung:
- Python beginnt die Index-Nummerierung bei 0, d. h. das erste Element ist nicht die 1, sondern die 0.
- Öffne Dateien wenn irgend möglich mit dem with statement. Damit stellst Du sicher, dass die Datei auch im Falle eines Fehlers ordnungsgemäß geschlossen wird.
- Innerhalb des try:...except:...Blocks wird zuerst versucht, die gewünschte Datei temporär zu schreiben. Gelingt dies aus irgendeinem Grunde nicht, wird die temporäre Datei gelöscht und der Fehler ausgelöst. Geht alles gut, wird die ursprüngliche Datei mit der erfolgreich erstellten neuen Datei ersetzt.
mutetella
EDIT: Und verwende `file` nicht als Namen, da Du dadurch die
built-in Funktion file überschreibst.
Re: Variable in Befehl einbauen
Verfasst: Freitag 3. Januar 2014, 18:50
von fenestro
Ich glaub ihr habt etwas falsch verstanden.
ich möchte nicht davor sondern stattdessen einsetzen.
mfg
fenestro
//edit:
hab folgenden Code geschrieben:
Code: Alles auswählen
import os
with open('/var/www/lol.txt', 'r') as input_file, open('/var/www/lol_new.txt', 'w') as output_file:
i = 0
while 1:
i = i+1
if i == 18:
break
if i == 2:
output_file.write('1\n')
else:
output_file.write(i-1)
os.rename('/var/www/lol_new.txt','/var/www/lol.txt')
bekomme aber den Error
output_file.write(i-1)
TypeError: expected a character buffer object
Re: Variable in Befehl einbauen
Verfasst: Freitag 3. Januar 2014, 18:58
von Sirius3
@fenestro: Du kannst auch keine Zahlen in Dateien schreiben, sondern nur Bytes. Dein Code benutzt input_file ja auch gar nicht. Wenn Du eine Zahl einfach hochzählen willst, dann benutz doch eine »for«-Schleife und keine »while«-Schleife.
Warum erweiterst Du nicht einfach mutetellas Beispiel:
Code: Alles auswählen
def substitute_with(iterable, start, stop, content):
iterable = iter(iterable)
return itertools.chain(
itertools.islice(iterable, start), content, itertools.islice(iterable, stop-start, None)
)
def substitute_lines(filename, start, stop, content):
tmp_filename = '{}.tmp'.format(filename)
with open(filename, mode='r') as orig_file:
with open(tmp_filename, mode='w') as tmp_file:
try:
tmp_file.writelines(
substitute_with(orig_file, start, stop, content)
)
except Exception:
os.remove(tmp_file)
raise
shutil.move(tmp_filename, filename)
substitute_lines('lol.txt', 2,3, ['1\n'])