Ein Feld aus einer Funktion übernehmen

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.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

LotharK hat geschrieben:Kann man nun eine Liste irgend wie als global definieren und in einer Funktion verändern?
Wenn man im Code die betreffende Liste referenziert, dann ist es völlig egal, ob sie global oder lokal ist. Die Antwort lautet also: Ja, aber tu es besser trotzdem nicht. ;)
BlackJack

@LotharK: Noch ein Grund warum man die Liste in der Funktion nicht verändern sollte: Wenn man die Liste verändert während jemand versucht sich anzumelden, wirds interessant. ;-)
LotharK
User
Beiträge: 51
Registriert: Sonntag 22. März 2015, 10:02

@snafu
Ja ist gut, ich bekomme sie aber trotzdem nicht von einem Modul ins andere - Siehe Soucecode ganz am Anfang.

@BlackJack

Überlege mal, was passiert, wenn ein Mitarbeiter sich anmeldet. Die Anmeldedaten stehen in der Liste. Die 'Liste wird durchlaufen - ( 0.1 Sek für 2000 Transponder). In der Zeit wurde die Liste verändert.
Die Datei wird im Interrupt kontrolliert, ob sie geändert wurde. Wurde sie geändert, wird sie neu eingelesen.

Die Liste wird in das Feld neu eingelesen und danach der Rest der Liste im Hauptprogramm weiter abgearbeitet.
Der Nutzer hat nun, entweder das Recht bekommen, oder entzogen bekommen. Oh, diese Entscheidung innerhalb einer 1/10 Sekunde ist schlimm!
Der andere Fall, es käme zu einem Laufzeitfehler (warum eigentlich?). Durch das Error-Konstrukt würde das Programm nicht abstürzen, sondern vorzeitig beenden. Der Mitarbeiter müsste den Transponder erneut ans Gerät halten. Wie oft kommt das vor?
Die Daten werden irgend wann mal geändert. Manchmal vergehen Monate. Sollte dieser Zufall wirklich auftreten - und was tut's????
Man sollte vielleicht nicht zu viel hineininterpretieren. Die ganze Sache ist viel zu simpel dafür.

:)
MfG LotharK
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

LotharK hat geschrieben:Ja ist gut, ich bekomme sie aber trotzdem nicht von einem Modul ins andere - Siehe Soucecode ganz am Anfang.
Wo ist da ein Modul? Ich sehe da nur Code auf Modulebene fürs Hauptprogramm und eine ominöse Funktion, die mit jedem Aufruf weitere Daten an ein global vorliegendes Objekt anhängt.

Hast du möglicherweise eine andere Vorstellung von Modul? Ich denke gerade eher an Python-Module - also einzeln vorliegende "*.py"-Dateien.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@LotharK: Wenn Du Dich irgendwo anmelden willst, mußt Du das Passwort, einen Hash des Passworts oder einen Private Key irgendwo hinterlegen, also irgendetwas was Dich als rechtmäßigen Zugreifer ausweist. Egal wie, wenn jemand die Zugangsdaten kopieren kann, hat er Zugriff. Deshalb ja der Vorschlag mit einem eigenen WebService, wo zu einer Transponder-ID nur abgefragt werden kann, ob der Zugang erlaubt wird oder nicht. Das Schadenspotential wird dadurch minimiert.

PS: je nach Design der Datei, der Art der Änderung wäre der schlimmste Anzunehmende Fall, dass die Zuordnung von Transponder-ID zu Rechten durcheinander gerät und jemand Zugang erhält, der das eigentlich nicht dürfte. Gegen diesen Fall mußt Du Deine Implementierung prüfen. Die Prüfung kann in bestimmten Fällen nicht trivial sein, also warum nicht gleich das ganze Problem umgehen, indem nie gleichzeitig auf gerade einlesende Daten zugegriffen werden kann.
BlackJack

@LotharK: Die Liste in das ”Feld” neu einlesen bedeutet doch aber das man erst den alten Inhalt löscht und dann mit den Daten vom Netzlaufwerk neu füllt. Das braucht Zeit. In dieser Zeit gibt es Leute die sich nicht anmelden können, weil ihre Daten noch nicht (wieder) in der Liste sind. Und wenn die Netzverbindung hängt oder langsam ist, wird's richtig lustig. Code der die globale, geteilte Liste aktualisiert müsste also deutlich komplexer sein um so etwas zu vermeiden, oder man sollte halt ganz einfach auf die selbe Liste nicht nebenläufig zugreifen und spart sich das somit. Und man kann dann auch eine saubere, vernünftige Funktion schreiben welche die Datei ausliest und eine *neue* Liste mit den Daten liefert. Beziehungsweise eine Datenstruktur die a) den Namen verdient und b) ein einfaches Testen auf das Recht erlaubt statt linear eine Liste mit Benutzerdaten durchlaufen zu müssen und dann vielleicht auch noch linear die Rechte.
LotharK
User
Beiträge: 51
Registriert: Sonntag 22. März 2015, 10:02

@BlackJack, glaub es bitte - die Liste einlesen passiert unter 1/10 sek.

Ich möchte das Thema auch nicht mehr weiter ausweiten. Das System steht hier und funktioniert. Auch ohne ständigen Netzzugriff. Zur Zeit zwar nur 3 Raspis, aber es macht genau das, was es soll.

Die ursprüngliche Frage war - wie ich auf eine Liste, welche in einer Function gefüllt wird, in einer anderen Routine lesen kann. Ich vermute mal, dass das nicht geht, da ja niemand eine Antwort hat.
Ich danke trotzdem noch mal allen und denke, das Thema ist erledigt. Zwar ohne Antwort auf die Frage, aber dafür habe ich ja ein brauchbares Script von Sirius3 erhalten

Ciao LotharK
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@LotharK: Genau, wenn Listen irgendwo geändert werden und das Auswirkungen auf eine andere Stelle im Code hat, wo diese Liste gelesen wird, dann ist es nicht einfach möglich, das fehlerfrei zu programmieren. Die Lösung ist ganz einfach, und wurde hier auch schon mehrfach genannt: man macht es anders.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Weil Das Wort Event-System gefallen ist, hier noch eine Version, mit ebensolchem: http://www.python-forum.de/pastebin.php ... &mode=view

Dabei gibt es zu Simulationszwecken für jede Tür einen eigenen Thread.

Die Anforderung, dass auf lokale Daten zugegriffen werden soll, wenn und solange ein Raspi keine Netzverbindung hat, kann man über das Proxy/State-Pattern lösen. Dazu hat man einen DB-Proxy, der alle Anfragen an die Remote-DB delegiert, und sollte das scheitern, wechselt man zu einer lokalen DB. Letztere braucht bloß dasselbe Interface zu besitzen wie die Remote-DB, braucht aber keine wirkliche DB mit allem Drum und Dran zu sein, sondern kann einfach mit Dictionaries implementiert sein, wie in meinem Beispiel. Man braucht bloß regelmäßig zu schauen, wann die Netzverbindung wieder steht und kann dann zurückschalten und die lokal angesamelten Daten flushen. Der Rest des Programms kann davon unbehelligt weiterlaufen, so wie es sein sollte. Und immer noch braucht es keine globale Liste.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

pillmuncher hat geschrieben:Weil Das Wort Event-System gefallen ist, hier noch eine Version, mit ebensolchem: http://www.python-forum.de/pastebin.php ... &mode=view
nice! :)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@LotharK: Glaub es mir, Netzlaufwerke können auch mal hängen. Und selbst wenn es das nie tun wird, wäre das trotzdem eine fehlerhafte Lösung. Warum sollte man etwas mit einem bekannten Fehler programmieren wollen wenn das sowieso keine saubere Lösung wäre, es aber durchaus fehlerfreie Lösungen gibt, wenn man sich denn nicht auf diesen „unbedingt globale Datenstrukturen haben wollen”-Ansatz versteifen würde?
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@BlackJack: manche wollen halt die einfachst-mögliche Lösung, egal, wie kompliziert sie ist.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Einfach-kompliziert klingt nach Max-Power-Art.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

pillmuncher hat geschrieben:manche wollen halt die einfachst-mögliche Lösung, egal, wie kompliziert sie ist.
Cooler Spruch. :mrgreen:
LotharK
User
Beiträge: 51
Registriert: Sonntag 22. März 2015, 10:02

@BlackJack

Langsam verstehe ich die Welt nicht mehr. Am Anfang hast Du mir diesen Code gepostet. Dieser Code macht haargenau das, was ich wollte. Jedenfalls im Grundgerüst.

Code: Alles auswählen


#!/usr/bin/env python
2.# coding: utf8
3.from __future__ import absolute_import, division, print_function
4. 
5.TRANSPONDER_FILENAME = '/mnt/netz/Python/Transponder.txt'
6. 
7. 
8.def load_transponders(filename):
9.    with open(filename, 'r') as lines:
10.        return [line.split(';') for line in lines if len(line) > 2]
11. 
12. 
13.def main():
14.    transponders = load_transponders(TRANSPONDER_FILENAME)
15.    for row in transponders:
16.        print(row[1])
17. 
18. 
19.if __name__ == '__main__':
20.    main()
Nun auf einmal ist alles falsch? Ich beobachte Foren, seit es sie gibt. Es ist egal welche. Aus einer simplen Frage werden dann Diskusionen, die die Welt nicht braucht. Simpelste Programmfunktionen werden in Klassen gepackt, etc.

Ich habe kürzlich im Microcontroller-Forum eine SMD-Leiterplatte vorgestellt, und gefragt, warum die Schaltung nicht funktioniert. Das Ergebnis: 3 Seiten Posting, was alles falsch wäre. Dass die Schaltung sowieso nicht funktionieren kann und das es die bei Ebay sowieso schon gibt.
Die Schaltung funktionierte übrigens vom ersten Tag an, bis heute perfekt. :D
Seit Mitte der 80er habe ich mit Computern zu tun. die Dinger werden immer schneller in der Prozessor-Leistung. Warum warte ich dann 5 Minuten auf einen Start? Und das bei einem Neugerät ohne schon etwas zu installieren?
Wenn ich sehe, wie aufgebläht viele Programme sind, kommt mir das K. Wieso passen manche Druckerinstallationen nicht mehr auf eine CD? Der Treiber ist höchstens 5MB. 5MB waren mal 5000000 Schreibmaschinenseite Soucecode.
:D
Tschüss
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Komisch, jeder Ausstehende erkennt das zuerst ein miserable Version eines Codes gepostet wurde mit der Anfrage nach Hilfe. Nachdem das gelöst wurde, hat der Fragende das Problem/Einsatzfeld beschrieben und hierfür Ideen und weiteren Code bekommen. Nun scheint dieser damit aber komplett überfordert zu sein.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@LotharK: BackJacks Code macht genau das, was wir die ganze Zeit schon schreiben. Das Lesen der Datei ist ein einer eigenen Funktion und es gibt keine globalen Variablen. Ich verstehe nicht, warum Du plötzlich meinst, das sei falsch.
Es ist aber nur ein Baustein in einer Aufgabe, die im Laufe des Threads immer umfangreicher wurde.
Ich habe versucht, eine speziell auf das Problem zugeschnittene minimalistische Lösung zu geben, die aber im Zweifel, wenn noch mehr Funktionen hinzukommen, nichts mehr taugt. Andere nehmen einen generalisierteren Ansatz, der für andere ähnliche Probleme wiederverwendbar ist, oder sich in einer beliebige Richtung erweitern läßt.

Es besteht ein Unterschied zwischen "tut im Normalfall" und "ist sicher gegen eine ganze Reihe von Störungen". Leute, die sich auf ersteres beschränken und sagen, das ist das was ich will, beschweren sich oft später, dass irgendetwas nicht so tut, wie gewünscht.

Es gibt Systeme, die sind auf möglichst schlank oder möglichst reaktionsschnell optimiert, andere auf möglichst kostengünstig, möglichst robust, möglichst funktionsumfangsreich oder irgend eine Mischung davon. Beim Kauf solltest Du Dich also informieren und das für Dich passende Gerät kaufen.
BlackJack

@LotharK: Wie Sirius3 schon anmerkt ist in dem zitierten Quelltext keine globale Liste sondern die Funktion `load_transponders()` bekommt den Dateinamen als Argument und liest die Daten in eine in dieser Funktion neu erstellten Liste ein, die dann zurückgegeben wird. So sollten Funktionen in der Regel aussehen, eine „black box” wo man etwas auf der einen Seite rein steckt, und auf der anderen Seite ein Ergebnis heraus fällt. Was immer dazwischen passiert sollte keine Effekte auf den Rest des Programms haben. So lassen sich Funktionen zum Beispiel sehr einfach isoliert testen, und wiederverwenden, und durch andere Implementierungen austauschen, und man kann auch einfacher über Vor- und Nachbedingungen reden wenn es um die Korrektheit geht.

Warum Du 5 Minuten auf einen Systemstart wartest weiss ich nicht, das musst Du mit dem Hersteller Deines Rechners ausmachen. Ich wette auch da ist schon was installiert — nämlich das Betriebssystem. Und je nach Hersteller eine Menge anderer Kram auch schon.

Ich habe mich aber auch schon gefragt warum mein C64 hier neben mir sofort nach dem Anschalten benutzbar ist und ich beim Laptop so verhältnissmässig lange auf den Desktop warten muss. Ich meine ich kann mit dem Laptop ja nicht mehr machen als mit dem C64… ;-)

Wenn Du etwas gegen aufgeblähte Programme hast, dann solltest Du vielleicht mal ganz grundsätzlich über Python nachdenken. Ein Programm das nur 'Hallo, Welt!' ausgibt belegt dafür zur Laufzeit auf dem Raspi cirka 3½ Megabyte Arbeitsspeicher. Auf meinem Laptop sogar 16 Megabyte. Beim Raspi gibt es einige Leute die sich das Betriebssystem ganz sparen und gleich in selbst geschriebenen Maschinencode booten. Es gibt da ein Projekt das in einen in Assembler geschriebenen BASIC-Interpreter bootet. So wie ich das in den 80ern gewohnt war. Ganz ohne „Bloat”. Damit etwas von einem Netzlaufwerk zu laden ist dann allerdings ein Problem. ;-)

Ich hätte für das Gesamtproblem auch den Ansatz von Sirius3 mit einer Queue und einer zentralen Ereignisschleife gewählt. Einfach aber erweiterbar. So können verschiedene Ereignisse unabhängig voneinander erfasst werden und zum Beispiel auch nebenher die Rechtedatenbank neu gelesen werden, aber es entstehen keine Probleme durch die Nebenläufigkeit weil die Ereignisse durch die Queue in eine serielle Abfolge gebracht werden. Und man muss keine globalen Datenstrukturen nebenläufig verändern, mit dem Rattenschwanz an Problemen die das nach sich zieht.
LotharK
User
Beiträge: 51
Registriert: Sonntag 22. März 2015, 10:02

@BlackJack - Ich habe nie explicit etwas von globalen Variablen geschrieben. Ich wollte den Code genau so, wie Du ihn mir anfangs gepostet hast. Dass ich diese Variable am Anfang vielleicht falsch verwendete, mag sein. Ich hatte es aber schon beim 1. Mal begriffen. 8)
OK - Ich schrieb, dass ich mit Python gerade beginne. Das diese simple und eigentlich im 3. Thread schon beantwortete Frage, solch Diskusionen auslöst, hätte ich nicht vermutet.

Der Code ist fertig und funktioniert. Netzwerk trennen - kein Problem. Daten neu einlesen, kein Problem. Mehr sollte das Programm nicht tun. Es ist einfach zu simpel, um so viele Worte darüber zu verlieren.
from_future_import hat mich zwar erst mal mit meinen Print aus der Bahn geworfen, steht auch in keinen der 2 Bücher, aber ich hab es begriffen.

Der PC - oder besser die PCs DELL zur Zeit 3020 mit Firmen-Image. Nachvollziebar an den letzten 56 diesen Jahres.

Hallo Welt - MsgBox "Hallo Welt" - in VB6 16KByte
Hallo Welt Assembler (ATMEL) an UART - 36 Byte (An LCD - OhJe)
Hallo Welt MsgBox in eMbedded - 3 KByte
Mehr will ich jetzt nicht testen

Belassen wir es jetzt dabei? Sicher gibt es für Euch interessantere Themen als das.


Kann ich das hier irgend wo schließen?
LotharK
BlackJack

@LotharK: Was sind das denn jetzt für Grössenangaben? Ich hatte ermittelt was der Prozess maximal zur Laufzeit an Speicher gleichzeitig im RAM hatte. Deins sieht mir eher nach Dateigrössen aus. Die Basis-DLLs von der VB6-Laufzeitumgebung bringen auch ca. 2 Megabyte zusammen.

Das entsprechende BASIC-Programm auf dem C64 belegt 20 Bytes:

Code: Alles auswählen

10 print"hallo, welt!"
Antworten