Seite 1 von 2
Liste erweitern mit variabler Anzahl
Verfasst: Donnerstag 19. Juni 2014, 22:14
von mobby
Hey Leute,
ich stehe vor folgendem Problem: Ich öffne eine Datei, die immer mit 111111 gefüllt ist, und ermittel die Länge des Strings bzw. in dem Fall die Anzahl der 1er. In diesem Beispiel 6. Nun möchte ich diese Anzahl an eine Liste übergeben, sprich eine leere Liste um 6 Mal eine 1 erweitern.
Mein Ansatz bisher:
Code: Alles auswählen
file = open('logfile','r')
laenge = len(file.read())
file.close()
liste = list()
... und jetzt 6 mal bzw. variabel gesehen: laenge * liste.append(1)
Mit was für einer Schleife kann/sollte ich hier arbeiten?
Vielen Dank für Feedback!
Re: Liste erweitern mit variabler Anzahl
Verfasst: Donnerstag 19. Juni 2014, 22:19
von Schorlem
Ich finde deinen Ansatz etwas umständlich, einfacher wäre das hier gewesen (ungetestet):
Code: Alles auswählen
file = open('logfile','r')
chars = file.read()
file.close()
liste = []
liste.extend(list(chars))
Re: Liste erweitern mit variabler Anzahl
Verfasst: Donnerstag 19. Juni 2014, 22:23
von mobby
Funktioniert und ist tatsächlich deutlich einfacher, vielen Dank das bringt mich weiter!
//edit: Aber wenn wir schon bei dem Thema Dateien sind, wie kann ich eine Datei öffnen und ans Ende eine "1" anhängen?
Re: Liste erweitern mit variabler Anzahl
Verfasst: Donnerstag 19. Juni 2014, 22:24
von BlackJack
@mobby: Da die Liste leer ist, es also gar nicht um das *erweitern* sondern um das *erstellen* geht, würde ich gar keine Schleife verwenden, sondern die Multiplikation auf einer Liste mit einer 1 drin. Ausserdem sollte man wenn möglich die Datei zusammen mit der ``with``-Anweisung öffnen, und dieses Konstrukt das sichere schliessen der Datei übernehmen lassen.
Edit:
Code: Alles auswählen
def main():
with open('logfile') as one_file:
result = [int(c) for c in one_file.read()]
Wobei ich mich gerade frage wozu das gut sein soll.
@Schorlem: Das weicht vom beschriebenen Ergebnis ein wenig ab weil dort Zahlen in der Liste stehen und keine Zeichenketten.
Re: Liste erweitern mit variabler Anzahl
Verfasst: Donnerstag 19. Juni 2014, 22:24
von EyDu
mobby hat geschrieben:Mit was für einer Schleife kann/sollte ich hier arbeiten?
Wenn die Anzahl der Durchläufe bekannt ist, dann verwendet man eine for-Schleife.
In diesem Fall geht es aber auch einfacher:
Du solltest dir auch angewöhnen Dateien mittels with-Statement zu öffnen, dann werden sie auch in jedem Fall, so weit das eben möglich ist, geschlossen. "file" ist auch ein schlechter Name für eine Datei. Zum einen sagt er nichts aus, zum anderen verdeckt er den vorhandenen file-Typ.
Re: Liste erweitern mit variabler Anzahl
Verfasst: Donnerstag 19. Juni 2014, 22:30
von mobby
@BlackJack: Das mit den Zahlen ist nicht so wichtig, es geht rein um die Anzahl, egal ob es Zahlen oder Strings sind. Den Hinweis mit der With Anweisung nehme ich gerne an, so funktioniert mein Code jetzt:
Code: Alles auswählen
with open('file','r') as f:
chars = f.read()
liste = []
liste.extend(list(chars))
print len(liste)
funktioniert!
Re: Liste erweitern mit variabler Anzahl
Verfasst: Donnerstag 19. Juni 2014, 22:54
von BlackJack
@mobby: Das ist immer noch deutlich zu umständlich das Du mit einer leeren Liste anfängst statt gleich die Liste zu erstellen. Überleg mal was ``list(chars)`` macht.
Bleibt immer noch die Frage wozu das gut sein soll.
Re: Liste erweitern mit variabler Anzahl
Verfasst: Donnerstag 19. Juni 2014, 23:05
von mobby
@BlackJack: Das steht in Zusammenhang mit einem anderen Thread von mir,
klick mich!. Dabei ist mein Ziel an der Stelle an der ich die Liste leading_edges um 1 erweitere noch eine Funtkion abzurufen, die eben eine 1 in eine logdatei schreibt. Sobald die Liste beim Übergeben an die MySQL geleert wird, soll auch der Inhalt der logdatei gelöscht werden und wieder von vorne gezählt werden. Im nächsten schritt wird dann ganz an den Anfang des Skriptes eine Abfrage der Logdatei gestellt, denn startet man das Skript und es sind bereits Einträge in der Logdatei, soll die Liste mit dieser Anzahl Starten bzw. erweitert werden.
Das skript wird nämlich von einem Watchdog überwacht, der über cronjobs alle Minute überprüft ob das Skript noch aktiv ist. Als Schutzmaßnahme, falls das Skript aus irgendeinem Grund heraus abstürtzen sollte.
Okay viel Gelaber, aber vielleicht bringt das etwas Licht ins Dunkle meiner Ansätze.

Re: Liste erweitern mit variabler Anzahl
Verfasst: Donnerstag 19. Juni 2014, 23:20
von pillmuncher
Re: Liste erweitern mit variabler Anzahl
Verfasst: Donnerstag 19. Juni 2014, 23:21
von BlackJack
@mobby: So richtig verstanden habe ich den Sinn der Datei nicht. Das was Dein watchdog macht lässt man üblicherweise entsprechende Programme erledigen die darauf spezialisiert sind. Zum Beispiel die daemontools oder supervisord. Die prüfen auch nicht periodisch, sondern die merken *sofort* wenn der Kindprozess weg stirbt.
Re: Liste erweitern mit variabler Anzahl
Verfasst: Freitag 20. Juni 2014, 07:45
von mobby
@BlackJack: Daemontools sieht echt gut aus, damit werde ich mich mal beschäftigen. Sobald mein Skript fertig ist werde ich es auf jeden Fall nochmals hochladen, um es hier auf Herz und Nieren prüfen zu lassen

Danke schonmal!
Re: Liste erweitern mit variabler Anzahl
Verfasst: Freitag 20. Juni 2014, 08:29
von mobby
Hey Leute, das ist mein ganzes Skript, um mal die Zusammenhänge erkennen zu lassen. Falls etwas auffällt, das man anders bzw. besser gestalten könnte, immer her damit. Zur Info, das Skript überwacht einen digitalen Eingang eines Mikrocontrollers und schreibt, falls HIGH-Werte anfallen, diese gesammelt über ein entsprechendes Zeitintervall in eine Datenbank.
Das Skript sollte dann, momentan noch ein Watchdog, über deamontools überwacht und am Leben gehalten werden.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
import os
from contextlib import closing
from itertools import groupby
from threading import Thread
from time import sleep
import MySQLdb as db
import pifacedigitalio as piface
def insert_into_database(timestamp, date, time, amount):
with closing(
db.connect(
host='localhost',
user='',
passwd='',
db='')
) as connection:
connection.cursor().execute(
'INSERT INTO Tabelle(Zeitstempel, Datum, Zeit, Impulsanzahl) VALUES (%s, %s, %s, %s)',
(timestamp, date, time, amount)
)
connection.commit()
def blink_led():
piface.digital_write(0,1)
sleep(0.1)
piface.digital_write(0,0)
def write_leading_edge_count(leading_edges):
intervall = 300
timestamp = int(time.time() / intervall) * intervall
while True:
timestamp += intervall
time.sleep(max(0, timestamp-time.time()))
leading_edge_count = len(leading_edges)
del leading_edges[:]
reset_logfile()
datum = str(time.strftime("%d-%m-%Y"))
uhrzeit = str(time.strftime("%H:%M:%S"))
insert_into_database(timestamp, datum, uhrzeit, leading_edge_count)
def start_writer(leading_edges):
thread = Thread(target=write_leading_edge_count, args=(leading_edges,))
thread.setDaemon(True)
thread.start()
def write_into_logfile(value):
with open('logfile','r') as lf:
lines = lf.readlines()
lines.insert(0,str(value))
with open('logfile' + '.new','w') as lfn:
lfn.writelines(lines)
os.rename('logfile' + '.new', 'logfile')
def read_logfile(liste):
with open('logfile','r') as lf:
chars = lf.read()
liste.extend(list(chars))
def reset_logfile():
with open('logfile','r+') as lf:
lf.truncate()
def iter_values(frequency):
while True:
yield piface.digital_read(0)
sleep(1.0 / frequency)
def iter_changes(frequency):
for value, _ in groupby(iter_values(frequency)):
yield value
def main():
piface.init()
leading_edges = list()
read_logfile(leading_edges)
start_writer(leading_edges)
for value in iter_changes(100):
if value == 1:
leading_edges.append(1)
write_into_logfile(1)
blink_led()
if __name__ == '__main__':
main()
Gruß
mobby
Re: Liste erweitern mit variabler Anzahl
Verfasst: Freitag 20. Juni 2014, 09:22
von Sirius3
@mobby: in Deiner Log-Datei steht also nichts sinnvolles, außer die Anzahl der Bytes. Statt dessen könnte man auch einfach eine Zahl schreiben. Warum schreibst Du einen Zeitstempel, Datum und Zeit in Deine Datenbank? Ein DATETIME-Feld würde doch völlig genügen.
Ist Dir bewusst, dass Deine Abtastfrequenz nicht sonderlich stabil ist und Du nach jedem 1-0-Übergang über 1/10 Sekunde blind bist?
Was für ein Signal willst Du denn überhaupt aufnehmen und was glaubst Du durch die log-Datei zu erreichen?
Re: Liste erweitern mit variabler Anzahl
Verfasst: Freitag 20. Juni 2014, 09:34
von mobby
@Sirius3:
1) Logdatei: Du hast recht, momentan stehen nur die Anzahl an Bytes darin, weiß nicht ob es sinnvoller ist eine Zahl zu schreiben? Für meine Zwecke reicht es aber eigentlich so.
2) Zeitstempel: Ja den brauche ich später für das Auslesen der Datenbank, etwas kompliziert, da die über Excel ausgewertet wird ... also brauche ich eben.
3) Abfragefrequenz: Ist mir nicht bewusst, liegt das momentan an der Frequenz an sich? Also ist das über anheben der Frequenz, sprich auf vlt. 200 zu beheben? Um etwas Hintergrundwissen reinzubringen, an dem digitalen Eingang ist eine S0-Schnittstelle angeschlossen. Die kann Impulse mit einer Dauer von 30 ms oder mehr liefern, also sollte die Abtastung so fein sein, dass es auch einen Impuls erkennt, der nur 30 ms dauert. Momentan verstehe ich das so, dass wenn ich eine Frequenz von 100 Eingebe, eine Abfrage pro 0,01 also pro Millisekunde stattfindet, also eine 0 oder eine 1 zurückgegeben wird. Das sollte doch auf jeden Fall ausreichen. Zudem probier ich das ständig in der Praxis aus und bisher gab es keine Bugs in der Hinsicht. Erst wenn ich die Frequenz unter 50 lege kommt es zu Aussetzern.
4) Logdatei2: Die Logdatei dient eigntlich nur dazu, dass falls das Skript aus irgendeinem Grund heraus abstürtzen sollte, die Impulse lokal zwischengespeichert werden.
Re: Liste erweitern mit variabler Anzahl
Verfasst: Freitag 20. Juni 2014, 10:14
von Sirius3
@mobby: Du meinst wohl, Du fragst die Schnittstelle alle 10ms ab, damit hast Du eine dreimal höhere Abtastrate als das Signal. Die Totzeit ist dann drei mal länger als das Signal. Die entscheidende Frage ist ja dann, wie lange die Zeit zwischen den Impulsen ist. Auf jeden Fall mußt Du das Ermitteln der Signale vom Schreiben in die Datei oder Datenbank trennen, also in verschiedenen Threads und über Queues getrennt, nicht Listen, die sind dafür nicht geeignet.
Zum Abstürzen: Programme stürzen nicht einfach ab. Dazu muß es zu einer Fehlfunktion kommen. Also solltest Du Dir erst eine Liste mit allen Fehlern, die passieren können machen und dann die Wahrscheinlichkeit, daß der Fehler auftritt, abschätzen. Auf die meisten Fehler kann Dein Programm, wenn es entsprechend programmiert ist, reagieren. Bleiben noch SIGKILL und Strom weg. Ersterer tritt nicht auf, wenn Du es nicht willst. Zweiterer bedeutet einen Ausfall von mindestens 10 Sekunden, was sich in x verpaßte Signale übersetzen läßt und dann stellt sich die Frage, ob Du mit der Zahl dann überhaupt noch etwas anfangen kannst.
Re: Liste erweitern mit variabler Anzahl
Verfasst: Freitag 20. Juni 2014, 13:11
von mobby
Sirius3 hat geschrieben:Auf jeden Fall mußt Du das Ermitteln der Signale vom Schreiben in die Datei oder Datenbank trennen, also in verschiedenen Threads und über Queues getrennt, nicht Listen, die sind dafür nicht geeignet.
Was bietet sich dann an? Eine Variable in der die absolute Anzahl übergeben wird? Und was spricht technisch gegen die Liste?
Und mit der Aussage das Skript stürtzt nicht ab ... dann kann ich mir ja den watchdog/deamontools sparen? Weil sonst hat das ja kaum Fehleranfälligkeit, außer dass jetzt z.B. die Datenbank Verbindung nicht funzt, aber die läuft auf dem gleichen System und es gibt auch keinen ersichtlichen Grund, dass die ausfallen sollte.
Re: Liste erweitern mit variabler Anzahl
Verfasst: Freitag 20. Juni 2014, 13:58
von BlackJack
@mobby: Gegen eine Liste spricht, dass die nicht threadsafe ist, beziehungsweise man sehr genau aufpassen muss was man damit anstellt und das keine der Operationen Probleme bei nebenläufiger Benutzung machen. Während der Queue-Typ threadsafe ist, was auch entsprechend in der Dokumentation garantiert wird. Ansonsten kann man auch eine Zahl hernehmen und die am besten in einer Klasse kapseln und die kritischen Abschnitte in den Operationen mit Sperren (z.B. `threading.Lock`) absichern. Die Länge einer Liste zum Zählen von etwas zu verwenden, ist IMHO ein Hack/Missbrauch solange man den Inhalt nicht tatsächlich für irgendwas benötigt.
Was das abstürzen angeht: Die Datenbankverbindung kann Probleme machen, auch wenn beides auf dem selben Rechner läuft, zum Beispiel Zeitüberschreitungen wenn das System an sich überlastet ist, Abbrüche der DB-Verbindung weil der Massenspeicher voll ist und die DB deshalb keine Daten mehr entgegen nehmen kann, andere Probleme mit dem Medium oder dem Dateisystem, blockierte Tabellen weil ein anderer Prozess ein Lock auf die Tabelle oder Datensätze hält, (zu) voller Arbeitsspeicher, und alles woran man jetzt gerade nicht denkt, was aber mal passieren kann.
Re: Liste erweitern mit variabler Anzahl
Verfasst: Freitag 20. Juni 2014, 14:39
von mobby
@BlackJack: Meinst du mit dem Queue-Typ folgendes?
Code: Alles auswählen
from collections import deque
queue = deque[]
queue.append("1")
BlackJack hat geschrieben:Ansonsten kann man auch eine Zahl hernehmen und die am besten in einer Klasse kapseln und die kritischen Abschnitte in den Operationen mit Sperren (z.B. `threading.Lock`) absichern. Die Länge einer Liste zum Zählen von etwas zu verwenden, ist IMHO ein Hack/Missbrauch solange man den Inhalt nicht tatsächlich für irgendwas benötigt.
Und wie mach ich das?

Re: Liste erweitern mit variabler Anzahl
Verfasst: Freitag 20. Juni 2014, 14:59
von BlackJack
@mobby: Eine `collections.deque` kann man auch nehmen, aber üblicherweise verwendet man für die Kommunikation zwischen Threads eine `Queue.Queue`.
Wie man geteilte Daten absichert hängt davon ab wie darauf zugegriffen wird und was dabei jeweils schief laufen kann wogegen man sich deshalb absichern muss.
Re: Liste erweitern mit variabler Anzahl
Verfasst: Freitag 20. Juni 2014, 17:19
von mobby
@BlackJack: Wie muss ich mir das vorstellen mit "queue.Queue"? Kann ich alle momentan mit Liste umgesetzen Dinge folgendermaßen ersetzen?
Und dann anstatt "leading_edges.append(1)" folgendermaßen weiter?
Und als letztes anstatt "leading_edge_count = len(leading_edges)"
Nur wie leere ich die Reihe wieder? Bzw. muss ich zusätzlich mit "leading_edges.join" und "leading_edges.task_done()" arbeiten? Oder ist so schon alles erfüllt?
Ich weiß, ich stell mich da ein bisschen dappig an, aber ich bin nun mal kein Programmierer und dieser Teil ist momentan nur ein kleiner Bereich meines Projektes. Danke nochmal!