Verständnisfragen zum Webframework und Python - Python Projekt realisierbar?

Django, Flask, Bottle, WSGI, CGI…
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Soulpilot: Du hast eine `main`-Funktion, die nichts macht, außer eine lokale Variable anlegen und die gleich wieder wegzuschmeißen.
Jetzt hast Du zusätzlich eine globale Variable definiert. Dass `cient` in der ursprünglichen Variante nicht definiert war und Du deshalb einen NameError bekommen hast, hättest Du irgendwo als Fehlermeldung sehen sollen. Wenn das nicht der Fall ist, mußt Du erst einmal herausfinden, warum, und wo die Fehlermeldung hingeschrieben wird, denn ohne diese Information ist eine Fehlersuche unmöglich.

Signale sind sehr sehr low-level, und benutzt man nicht. Zum Aufräumen kennt Python finally-Blöcke. Vielleicht sorgte ja Dein Signal-Handler dafür, dass Fehlermeldungen verschluckt werden, da kann alles mögliche unvorhersehbares passieren.

Importe gehören immer an den Anfang der Datei und keine Konstanten dazwischen. time und pdb werden nicht benutzt, aber importiert, sys und signal sollten nicht benutzt werden.

`main` ist nicht nur einfach so da, sondern enthält das gesamte Hauptprogramm. Du hast das Hauptprogramm aber über den ganzen Code verteilt.

Code: Alles auswählen

from functools import partial
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
from SimpleWebSocketServer import WebSocket, SimpleWebSocketServer

UNIT = 0x1
HOST = '192.168.0.50'
PORT = 502
COILBASE = 512 # Coil Output Base Address

PORTNUM = 8001

# Websocket class to echo received data
class Echo(WebSocket):

    def __init__(self, client, server, sock, address):
        super().__init__(server, sock, address)
        self.client = client

    def handleMessage(self):
        print("Echoing '%s'" % self.data)
        self.sendMessage(self.data)

        command = self.data
        address, value = {
            'relaise1': (COILBASE + 0, True),
            'relaise1off': (COILBASE + 0, False),
            'relaise2': (COILBASE + 1, True),
            'relaise2off': (COILBASE + 1, False),
        }[command]
        rq = self.client.write_coil(address, value, unit= UNIT)

    def handleConnected(self):
        print("Connected")

    def handleClose(self):
        print("Disconnected")     


def main():
    with ModbusClient(host=HOST, port=PORT) as client:
        client.connect()

        print("Websocket server on port %s" % PORTNUM)
        server = SimpleWebSocketServer('', PORTNUM, partial(Echo, client))
        try:
            server.serveforever()
        finally:
            server.close()


if __name__ == "__main__":
    main()
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

__deets__ hat geschrieben: Donnerstag 28. April 2022, 08:41 Aus meiner Perspektive ist das kein lauffaehiger Code. Denn der Socket-Handler wird nirgendwo genutzt. Und er ist *sehr* verquast, mit allem moeglichen unnoetigen, doppeltem, unsortiertem.
Er läuft aber, wie kann man es besser machen?
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Soulpilot: wie man es besser macht, habe ich Dir doch gezeigt :roll: :roll:
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Sirius3 hat geschrieben: Donnerstag 28. April 2022, 09:04 @Soulpilot: Du hast eine `main`-Funktion, die nichts macht, außer eine lokale Variable anlegen und die gleich wieder wegzuschmeißen.
Jetzt hast Du zusätzlich eine globale Variable definiert. Dass `cient` in der ursprünglichen Variante nicht definiert war und Du deshalb einen NameError bekommen hast, hättest Du irgendwo als Fehlermeldung sehen sollen. Wenn das nicht der Fall ist, mußt Du erst einmal herausfinden, warum, und wo die Fehlermeldung hingeschrieben wird, denn ohne diese Information ist eine Fehlersuche unmöglich.

Signale sind sehr sehr low-level, und benutzt man nicht. Zum Aufräumen kennt Python finally-Blöcke. Vielleicht sorgte ja Dein Signal-Handler dafür, dass Fehlermeldungen verschluckt werden, da kann alles mögliche unvorhersehbares passieren.

Importe gehören immer an den Anfang der Datei und keine Konstanten dazwischen. time und pdb werden nicht benutzt, aber importiert, sys und signal sollten nicht benutzt werden.

`main` ist nicht nur einfach so da, sondern enthält das gesamte Hauptprogramm. Du hast das Hauptprogramm aber über den ganzen Code verteilt.

Code: Alles auswählen

from functools import partial
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
from SimpleWebSocketServer import WebSocket, SimpleWebSocketServer

UNIT = 0x1
HOST = '192.168.0.50'
PORT = 502
COILBASE = 512 # Coil Output Base Address

PORTNUM = 8001

# Websocket class to echo received data
class Echo(WebSocket):

    def __init__(self, client, server, sock, address):
        super().__init__(server, sock, address)
        self.client = client

    def handleMessage(self):
        print("Echoing '%s'" % self.data)
        self.sendMessage(self.data)

        command = self.data
        address, value = {
            'relaise1': (COILBASE + 0, True),
            'relaise1off': (COILBASE + 0, False),
            'relaise2': (COILBASE + 1, True),
            'relaise2off': (COILBASE + 1, False),
        }[command]
        rq = self.client.write_coil(address, value, unit= UNIT)

    def handleConnected(self):
        print("Connected")

    def handleClose(self):
        print("Disconnected")     


def main():
    with ModbusClient(host=HOST, port=PORT) as client:
        client.connect()

        print("Websocket server on port %s" % PORTNUM)
        server = SimpleWebSocketServer('', PORTNUM, partial(Echo, client))
        try:
            server.serveforever()
        finally:
            server.close()


if __name__ == "__main__":
    main()
Hi Sirius3,

vielen lieben Dank, das sieht schon ordentlicher aus, ich würde das heute noch testen und mich wieder melden! Ja, das mit der main() stimmt, die hat sich durch das ganze Programm gezogen, ich wusste nicht genau wo hin damit^^

Ach was mir gerade noch einfällt ist, dass das mit der Fehlerrückgabe bei der Sockeverbindung mit einem Disconnect gehandhabt wird. Also bei meinen Versuchen, ist einfach die Verbindung abgebrochen, eine Fehlermeldung kam dabei nicht herum, ich weiß jetzt nicht, wie es da in den Bibliotheken von simplesocket aussieht, aber es könnte sein, dass die das so implementiert haben?

Also gut, ich werde versuchen, das zu verstehen, was Du mir aufgeschrieben hast, noch mal tausend Dank dafür!!! Ich melde mich wieder... :-)

LG

Soulpilot
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Sirius3 hat geschrieben: Donnerstag 28. April 2022, 15:05 @Soulpilot: wie man es besser macht, habe ich Dir doch gezeigt :roll: :roll:
Ich hatte deine Nachricht noch nicht gelesen gehabt, war blödes timing, sorry!
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Sirius3 hat geschrieben: Donnerstag 28. April 2022, 09:04 [...]
Hab das kurz mal ausgetestet, kann aber leider keine Socketverbindung aufbauen?

Code: Alles auswählen

Websocket server on port 8001
Traceback (most recent call last):
  File "websock_neu.py", line 52, in <module>
    main()
  File "websock_neu.py", line 46, in main
    server.serveforever()
  File "/home/user/.local/lib/python3.8/site-packages/SimpleWebSocketServer/SimpleWebSocketServer.py", line 697, in serveforever
    self.serveonce()
  File "/home/user/.local/lib/python3.8/site-packages/SimpleWebSocketServer/SimpleWebSocketServer.py", line 639, in serveonce
    rList, wList, xList = select(self.listeners, writers, self.listeners, self.selectInterval)
OSError: [Errno 9] Bad file descriptor
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Ja, das ist die blöde Vererbung, da die Elternklasse schon self.client benutzt (Aber wer kann schon ahnen, dass die Socke als Attribut ein Klient wird). Du mußt hier self.client in self.modbus oder so ähnlich umbenennen.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Sirius3 hat geschrieben: Donnerstag 28. April 2022, 16:43 Ja, das ist die blöde Vererbung, da die Elternklasse schon self.client benutzt (Aber wer kann schon ahnen, dass die Socke als Attribut ein Klient wird). Du mußt hier self.client in self.modbus oder so ähnlich umbenennen.
Ich komme mir echt schon dumm vor... er baut so einfach keine Verbindung auf.

Bild

Code: Alles auswählen

from functools import partial
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
from SimpleWebSocketServer import WebSocket, SimpleWebSocketServer

UNIT = 0x1
HOST = '192.168.0.50'
PORT = 502
COILBASE = 512 # Coil Output Base Address

PORTNUM = 8001

# Websocket class to echo received data
class Echo(WebSocket):

    def __init__(self, modbus, client, server, sock, address):
        super().__init__(server, sock, address)
        self.modbus = client

    def handleMessage(self):
        print("Echoing '%s'" % self.data)
        self.sendMessage(self.data)

        command = self.data
        address, value = {
            'relaise1': (COILBASE + 0, True),
            'relaise1off': (COILBASE + 0, False),
            'relaise2': (COILBASE + 1, True),
            'relaise2off': (COILBASE + 1, False),
        }[command]
        rq = self.client.write_coil(address, value, unit= UNIT)

    def handleConnected(self):
        print("Connected")

    def handleClose(self):
        print("Disconnected")


def main():
    with ModbusClient(host=HOST, port=PORT) as client:
        client.connect()

        print("Websocket server on port %s" % PORTNUM)
        server = SimpleWebSocketServer('', PORTNUM, partial(Echo, client))
        try:
            server.serveforever()
        finally:
            server.close()


if __name__ == "__main__":
    main()
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

wozu dient eigentlich das partial(...) wird dort das cient von der modbus lib an die Klasse übergeben?

Code: Alles auswählen

server = SimpleWebSocketServer('', PORTNUM, partial(Echo, client))
Ich habe statt client in der Klasse auch modbus ausprobiert, leider ohne Erfolg :-(

Code: Alles auswählen

self.modbus = modbus
und hier muss denke ich zwingend ein client.write vorhanden sein?

Code: Alles auswählen

 rq = self.modbus.write_coil(address, value, unit= UNIT)
also das client von ModbusClient aus main muss irgendwie in die klasse oben... sehe ich das richtig?
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Richtig, es muß self.modbus.write_coil heißen.
Wenn ich diesen Websocket-Code genau anschaue, werden tatsächlich alle Exceptions einfach verschluckt. Um also Fehler zu sehen, muß man selbst dafür sorgen, dass sie ausgegeben werden:

Code: Alles auswählen

import logging
from functools import partial
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
from SimpleWebSocketServer import WebSocket, SimpleWebSocketServer
logger = logging.getLogger(__name__)

UNIT = 0x1
HOST = '192.168.0.50'
PORT = 502
COILBASE = 512 # Coil Output Base Address

PORTNUM = 8001

# Websocket class to echo received data
class Echo(WebSocket):

    def __init__(self, client, server, sock, address):
        super().__init__(server, sock, address)
        self.modbus = client

    def handleMessage(self):
        try:
            print("Echoing '%s'" % self.data)
            self.sendMessage(self.data)

            command = self.data
            address, value = {
                'relaise1': (COILBASE + 0, True),
                'relaise1off': (COILBASE + 0, False),
                'relaise2': (COILBASE + 1, True),
                'relaise2off': (COILBASE + 1, False),
            }[command]
            rq = self.modbus.write_coil(address, value, unit= UNIT)
        except Exception as exception:
            logger.exception("handle message")
            raise

    def handleConnected(self):
        print("Connected")

    def handleClose(self):
        print("Disconnected")


def main():
    logging.basicConfig()
    with ModbusClient(host=HOST, port=PORT) as client:
        client.connect()

        print("Websocket server on port %s" % PORTNUM)
        server = SimpleWebSocketServer('', PORTNUM, partial(Echo, client))
        try:
            server.serveforever()
        finally:
            server.close()


if __name__ == "__main__":
    main()
Edit: Echo.__init__ korrigiert.
Zuletzt geändert von Sirius3 am Donnerstag 28. April 2022, 18:35, insgesamt 1-mal geändert.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Sirius3 hat geschrieben: Donnerstag 28. April 2022, 18:10 Richtig, es muß self.modbus.write_coil heißen.
Wenn ich diesen Websocket-Code genau anschaue, werden tatsächlich alle Exceptions einfach verschluckt. Um also Fehler zu sehen, muß man selbst dafür sorgen, dass sie ausgegeben werden:

Code: Alles auswählen

def main():
    logging.basicConfig()
    with ModbusClient(host=HOST, port=PORT) as client:
        client.connect()

        print("Websocket server on port %s" % PORTNUM)
        server = SimpleWebSocketServer('', PORTNUM, partial(Echo, client))
        try:
            server.serveforever()
        finally:
            server.close()


if __name__ == "__main__":
    main()
Da müsste was anderes nicht passen, wenn ich auf "connect" drücke, baut der Socket-Client keine Verbindung auf?

Was macht das hier?

Code: Alles auswählen

signal.signal(signal.SIGINT, close_server)
Irgendwo muss ein Fehler sein, unabhängig von self.modbus oder self.client
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

In Echo.__init__ hast Du ja jetzt einen weiteres Argument `modbus` engebaut. Warum?
Auch beim Initialisieren der Klasse werden Exceptions einfach verschluckt. Die Bibliothek `SimpleWebSocketServer` ist wirklich Schrott.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Sirius3 hat geschrieben: Donnerstag 28. April 2022, 18:34 In Echo.__init__ hast Du ja jetzt einen weiteres Argument `modbus` engebaut. Warum?
Auch beim Initialisieren der Klasse werden Exceptions einfach verschluckt. Die Bibliothek `SimpleWebSocketServer` ist wirklich Schrott.
Ah stimmt, das modbus im __init__ ist falsch. Danke!

Oke ich habe es noch mal getestet und er connected aber sobald ich einen Button drücke springt er raus und bricht die Verbindung ab...

Code: Alles auswählen

Websocket server on port 8001
Connected
Echoing 'relais1'
ERROR:__main__:handle message
Traceback (most recent call last):
  File "websock_neu3.py", line 27, in handleMessage
    address, value = {
KeyError: 'relais1'
Disconnected
Connected
Echoing 'relais1off'
ERROR:__main__:handle message
Traceback (most recent call last):
  File "websock_neu3.py", line 27, in handleMessage
    address, value = {
KeyError: 'relais1off'
Disconnected
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Sehr schön, jetzt wird eine sinnvolle Fehlermeldung ausgegeben.
Die Lösung des Problems sollte mit minimalen Pythongrundkenntnissen möglich sein.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Sirius3 hat geschrieben: Donnerstag 28. April 2022, 18:54 Sehr schön, jetzt wird eine sinnvolle Fehlermeldung ausgegeben.
Die Lösung des Problems sollte mit minimalen Pythongrundkenntnissen möglich sein.
stimmt^^ haha Danke Danke!!! würd dir nen "kaffee" ausgeben, wenn du mir deine papal adresse da lässt ;-)

Lösung -Y relasie1 = relais1 -> läuft

LG
Antworten